Unity中使用Input System调用父类方法并引用子类变量的问题
问题解决:Input System调用父类方法时子类变量未被识别
核心原因
你在子类PlayerController中重复定义了父类已有的public GameObject projectile变量,这会隐藏父类的同名成员。当调用父类的FireProjectile方法时,方法访问的是父类中未赋值的projectile,而非子类中已赋值的同名变量,因此触发UnassignedReferenceException。
解决方案1:移除子类重复变量(推荐)
直接使用父类继承的projectile变量,不要在子类中重新定义:
修改后的子类代码
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.InputSystem; public class PlayerController : CharacterController { PlayerControl playerControl; // 移除重复定义的projectile变量 // public GameObject projectile; void Start() { // 直接给继承自父类的projectile赋值 projectile = base.mainManager.projectiles[0]; playerControl = new PlayerControl(); playerControl.Player.Enable(); // 直接绑定继承的方法(无需base,this可省略) playerControl.Player.Fire.performed += FireProjectile; } }
父类代码无需修改,此时FireProjectile方法会正确访问到子类赋值的projectile变量。
解决方案2:重写父类方法(适用于特殊需求)
如果确实需要子类维护独立的projectile变量,可重写父类的FireProjectile方法,在子类方法中使用自身变量:
父类代码(保持virtual)
public virtual void FireProjectile(InputAction.CallbackContext context) { if (context.performed) { Instantiate(projectile); } }
子类代码
using System.Collections; using System.Collections; using UnityEngine; using UnityEngine.InputSystem; public class PlayerController : CharacterController { PlayerControl playerControl; // 子类独立的projectile变量 public GameObject projectile; void Start() { projectile = base.mainManager.projectiles[0]; playerControl = new PlayerControl(); playerControl.Player.Enable(); // 绑定子类重写后的方法 playerControl.Player.Fire.performed += FireProjectile; } // 重写父类方法 public override void FireProjectile(InputAction.CallbackContext context) { if (context.performed) { // 使用子类自身的projectile Instantiate(projectile); } } }
关于你之前尝试的错误解释
你尝试给FireProjectile添加参数并直接调用base.FireProjectile(projectile),这不符合Input System回调的委托要求:
- Input System的
performed事件需要的是Action<InputAction.CallbackContext>类型的委托,直接调用方法会返回void,无法转换为委托类型。 - 如果需要传递额外参数,应该用lambda表达式包裹(不推荐,因为继承变量已足够):
// 父类方法修改为带参数 public virtual void FireProjectile(InputAction.CallbackContext context, GameObject tempProjectile) { if (context.performed) { Instantiate(tempProjectile); } } // 子类绑定事件时用lambda传递参数 playerControl.Player.Fire.performed += context => base.FireProjectile(context, projectile);
内容的提问来源于stack exchange,提问作者jeremy.bartlett
相关产品推荐
相关产品推荐

