Unity中Player类transform.position为空触发NullReferenceException问题
问题根因
触发空引用的核心错误是继承自MonoBehaviour的类不允许直接通过new关键字创建实例:你在Controller脚本中写的Player player = new Player();生成的是脱离Unity GameObject生命周期的裸类对象,没有绑定任何场景对象,自然取不到transform属性,和你场景中已经挂载了Player脚本的Player对象是两个完全无关的实例。
修复方案
- 修改Controller脚本的Player变量声明,删除错误的new实例化逻辑,改为public序列化字段方便Inspector赋值:
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Controller : MonoBehaviour { // 替换原有new Player()行,改为public声明 public Player player; void Start() { player.SetEndpos(new Vector3(0f, 0f, 0f)); } void Update() { if (Input.GetKeyDown(KeyCode.Space)) { int roll = Random.Range(1, 7); player.SetEndpos(new Vector3(roll, 0f, 0f)); } player.Run(); } }
- 回到Unity编辑器,选中挂载了Controller脚本的Manager对象,在Inspector面板的Controller组件中找到
player字段,将场景里挂载了Player脚本的Player对象拖入该字段完成赋值。 - (可选优化)Player脚本中
if (transform.position != null)判断完全无效,Vector3是值类型不可能为null,可直接删除,简化后的Run方法如下:
public void Run() { transform.position += endPos; if (endPos != Vector3.zero) { Debug.Log($"pos was set to: {endPos}"); } }
其他替代实现(无需手动拖赋值)
如果不想在Inspector面板手动赋值,也可以在Controller的Start方法中通过Unity内置API获取场景中的Player实例:
void Start() { // 按对象名查找,需保证和场景中Player对象的名称完全一致 player = GameObject.Find("Player").GetComponent<Player>(); player.SetEndpos(new Vector3(0f, 0f, 0f)); }
通用排查思路
- 所有继承自MonoBehaviour的脚本,一律不能用
new创建实例,只能通过Inspector赋值、GetComponent、FindObjectOfType、AddComponent这类Unity官方提供的API获取有效实例 - 出现MonoBehaviour内置属性(transform、gameObject等)空引用时,优先检查当前脚本实例是否是通过合法方式生成、是否正确绑定到了场景中的GameObject上
内容的提问来源于stack exchange,提问作者Michael Yorgi
相关产品推荐
相关产品推荐

