Unity中从Delivery类向CustomerScript类导入变量i失败求助
问题分析与解决方案
核心问题
你在CustomerScript中通过Delivery abc = new Delivery();创建了一个全新的Delivery实例,这个实例和场景中挂载在玩家对象上的Delivery完全无关,因此永远无法获取到碰撞后更新的i值。
解决方案
方案一:Inspector手动引用(最简单直观)
修改CustomerScript,将Delivery字段设为可在Unity编辑器中赋值的类型,然后手动关联场景中的Delivery组件:
using UnityEngine; public class CustomerScript : MonoBehaviour { // 用[SerializeField]让字段在Inspector面板可见,也可直接设为public [SerializeField] private Delivery delivery; void Update() { // 先判断引用是否有效,避免空引用错误 if (delivery != null && delivery.i == 1) { transform.position = new Vector3(8.22f, 16.52f, -16f); // 可选:执行后重置i,防止重复触发位置修改 // delivery.i = 0; } } }
操作步骤:选中挂载CustomerScript的精灵物体,在Inspector面板找到CustomerScript组件,将场景中挂载了Delivery的玩家对象拖到delivery字段上。
方案二:代码动态查找(无需手动赋值)
如果不想手动关联引用,可在Start方法中自动查找场景中的Delivery组件:
using UnityEngine; public class CustomerScript : MonoBehaviour { private Delivery delivery; void Start() { // 查找场景中第一个Delivery组件 delivery = FindObjectOfType<Delivery>(); // 若场景中有多个Delivery,建议给玩家对象加专属标签(比如"Player"),用以下方式查找更高效: // delivery = GameObject.FindWithTag("Player").GetComponent<Delivery>(); } void Update() { if (delivery != null && delivery.i == 1) { transform.position = new Vector3(8.22f, 16.52f, -16f); } } }
注意:FindObjectOfType在复杂场景中效率较低,优先推荐标签查找方式。
方案三:事件系统(解耦性最强,推荐)
通过事件通知的方式,让Delivery在触发碰撞时主动通知CustomerScript,无需互相引用,代码解耦性更好:
- 修改
Delivery.cs,添加触发事件:
using UnityEngine; public class Delivery : MonoBehaviour { public int i = 0; public int Score = 0; // 修正拼写错误:Sccore → Score // 定义事件,当触发Stone碰撞时调用 public static event System.Action OnStoneDelivered; void OnTriggerEnter2D(Collider2D other) { if (other.CompareTag("Stone")) { Debug.Log("Triggered!!!"); i = 1; Destroy(other.gameObject); // 触发事件,通知所有订阅者 OnStoneDelivered?.Invoke(); } if (other.CompareTag("EditorOnly")) { Score += 1; Debug.Log("Score: 1"); Destroy(other.gameObject); } } }
- 修改
CustomerScript.cs,订阅事件:
using UnityEngine; public class CustomerScript : MonoBehaviour { void OnEnable() { // 订阅事件 Delivery.OnStoneDelivered += OnStoneDeliveredHandler; } void OnDisable() { // 取消订阅,避免内存泄漏 Delivery.OnStoneDelivered -= OnStoneDeliveredHandler; } private void OnStoneDeliveredHandler() { // 收到通知后修改位置 transform.position = new Vector3(8.22f, 16.52f, -16f); } }
额外注意事项
- 碰撞触发条件:确保
Stone对象的Collider2D勾选了Is Trigger,或者玩家对象的Collider2D勾选了Is Trigger,且至少一个对象带有Rigidbody2D(你的玩家对象已满足),否则OnTriggerEnter2D不会触发。 - 变量命名规范:建议将
i改为更具语义的名称(比如isStoneDelivered),提升代码可读性。
内容的提问来源于stack exchange,提问作者Vishist Parashar
相关产品推荐
相关产品推荐

