Unity自定义事件无法触发的问题排查与解决
Unity顾客离开事件未触发问题排查与解决
问题背景
开发游戏时实现以下流程:生成顾客→顾客前往餐桌→等待后返回生成点→删除顾客并触发事件通知生成更多顾客。当前其他功能正常,但事件触发后无响应,监听器日志未输出。
代码实现情况
CustomerMovement脚本中定义并触发OnCustomerLeaves事件CustomerSpawnManager脚本尝试订阅该事件,但未收到触发通知
相关代码
CustomerMovement 脚本
using System; using System.Collections; using System.Collections.Generic; using UnityEngine; public class CustomerMovement : MonoBehaviour { public event EventHandler OnCustomerLeaves; private Vector3 startingPos; [SerializeField] private List<GameObject> seatingOptionsList; private GameObject seatingSpot; private bool atSpot = false; private float speedValue = 3.0f; private float speed; private float waitTimer = 5.0f; private void Start() { startingPos = transform.position; PickRandomSeat(); } private void Update() { HandleMovement(); } private void PickRandomSeat() { int randomSeatingSpot = UnityEngine.Random.Range(0, seatingOptionsList.Count); seatingSpot = seatingOptionsList[randomSeatingSpot]; } private void HandleMovement() { if (atSpot == false) { speed = speedValue * Time.deltaTime; Vector3 modSeatingPosition = new Vector3(seatingSpot.transform.position.x, seatingSpot.transform.position.y + 1, seatingSpot.transform.position.z); transform.position = Vector3.MoveTowards(transform.position, modSeatingPosition, speed); if (transform.position == modSeatingPosition) { atSpot = true; } } if (atSpot == true) { waitTimer -= Time.deltaTime; if (waitTimer <= 0) { transform.position = Vector3.MoveTowards(transform.position, startingPos, speed); if (transform.position == startingPos) { DestroyCustomer(); } } } } private void DestroyCustomer() { OnCustomerLeaves?.Invoke(this, EventArgs.Empty); Debug.Log("Called"); gameObject.SetActive(false); } }
CustomerSpawnManager 脚本
using System.Collections; using System.Collections.Generic; using UnityEngine; public class CustomerSpawnManager : MonoBehaviour { [SerializeField] private GameObject customerPrefab; private CustomerMovement customerMovement; private float spawnRate = 2.0f; private float spawnRateMax = 2.0f; private int maxCustomers = 3; private int currentCustomers = 0; private void Start() { customerMovement = customerPrefab.GetComponent<CustomerMovement>(); customerMovement.OnCustomerLeaves += CustomerMovement_OnCustomerLeaves; } private void CustomerMovement_OnCustomerLeaves(object sender, System.EventArgs e) { Debug.Log("Maybe"); } private void Update() { if (currentCustomers < maxCustomers) { SpawnCustomers(); } } private void SpawnCustomers() { spawnRate -= Time.deltaTime; if (spawnRate <= 0) { var customer = Instantiate(customerPrefab, transform.position, customerPrefab.transform.rotation); customer.transform.parent = gameObject.transform; currentCustomers++; Debug.Log("Customers: " + currentCustomers); spawnRate = spawnRateMax; } } }
问题解决
原代码中在Start()方法里直接订阅预制体上的CustomerMovement事件,但实际运行时生成的是预制体的实例,实例上的事件并未被订阅。将获取组件和订阅事件的逻辑移至预制体实例化之后,即可正常接收事件触发通知。
内容的提问来源于stack exchange,提问作者Dylan Baum
相关产品推荐
相关产品推荐

