Unity打印机纸张投递故障:仅首张可投递问题求助
解决Unity纸张投递仅首张生效的问题
我开发的Unity游戏核心机制是向打印机投递纸张,但现在只有第一张纸能正常投递,后续纸张完全没反应。我发现问题出在DepositPaper脚本里的Paper变量是绑定的固定对象,试过用CompareTag修复,但没效果。相关代码如下:
纸张投递脚本(DepositPaper.cs)
using System.Collections; using System.Collections.Generic; using Unity.VisualScripting; using UnityEngine; using UnityEngine.InputSystem; using UnityEngine.SceneManagement; using TMPro; public class DepositPaper : MonoBehaviour { public GameObject Paper; public int PaperCount = 0; public TextMeshPro paperText; public float raycastDistance = 100f; public LayerMask interactableLayer; void Start() { } void destroyPaper() { Destroy(Paper); } void Update() { Ray ray = new Ray(transform.position, transform.forward); if (Physics.Raycast(ray, out RaycastHit hit, raycastDistance, interactableLayer) && hit.collider.gameObject.CompareTag("Printer")) { if(Input.GetKeyDown("e") ) { destroyPaper(); PaperCount++; paperText.text = "Paper:" + PaperCount.ToString() + "/11"; } } if(PaperCount == 2) { GameObject[] deadTaggedObjects = GameObject.FindGameObjectsWithTag("Dead_1"); foreach (GameObject deadtagged in deadTaggedObjects) { deadtagged.SetActive(false); } } } }
可拾取物品声明脚本(PickableItem.cs)
using UnityEngine; /// <summary> /// 挂载此脚本可让物体变为可拾取状态 /// </summary> [RequireComponent(typeof(Rigidbody))] public class PickableItem : MonoBehaviour { // 刚体组件引用 private Rigidbody rb; public Rigidbody Rb => rb; /// <summary> /// 初始化时调用 /// </summary> private void Awake() { // 获取刚体组件引用 rb = GetComponent<Rigidbody>(); } }
物品拾取脚本(SimpleGrabSystem.cs)
using UnityEngine; /// <summary> /// 简单的物品抓取系统示例 /// </summary> public class SimpleGrabSystem : MonoBehaviour { // 角色相机引用 [SerializeField] private Camera characterCamera; // 放置拾取物品的插槽引用 [SerializeField] private Transform slot; // 当前持有的物品引用 public PickableItem pickedItem; /// <summary> /// 每帧调用 /// </summary> private void Update() { // 仅在按下F键时执行逻辑 if (Input.GetKeyDown("f")) { // 检查是否已持有物品 if (pickedItem) { // 如果是,放下当前物品 DropItem(pickedItem); } else { // 如果没有,尝试拾取前方物品 // 从屏幕中心发射射线 var ray = characterCamera.ViewportPointToRay(Vector3.one * 0.5f); RaycastHit hit; // 发射射线寻找可拾取物体 if (Physics.Raycast(ray, out hit, 1.5f)) { // 检查物体是否可拾取 var pickable = hit.transform.GetComponent<PickableItem>(); // 如果物体带有PickableItem组件 if (pickable) { // 拾取物品 PickItem(pickable); } } } } } /// <summary> /// 拾取物品的方法 /// </summary> /// <param name="item">要拾取的物品</param> private void PickItem(PickableItem item) { // 赋值当前持有物品引用 pickedItem = item; // 禁用刚体并重置速度 item.Rb.isKinematic = true; item.Rb.linearVelocity = Vector3.zero; item.Rb.angularVelocity = Vector3.zero; // 将插槽设为父物体 item.transform.SetParent(slot); // 重置位置和旋转 item.transform.localPosition = Vector3.zero; item.transform.localEulerAngles = Vector3.zero; } /// <summary> /// 放下物品的方法 /// </summary> /// <param name="item">要放下的物品</param> private void DropItem(PickableItem item) { // 清空持有物品引用 pickedItem = null; // 移除父物体 item.transform.SetParent(null); // 启用刚体 item.Rb.isKinematic = false; // 添加力让物品被抛出一点距离 item.Rb.AddForce(item.transform.forward * 2, ForceMode.VelocityChange); } }

问题根源与修复方案
核心问题是DepositPaper脚本里的Paper变量是固定绑定的对象,销毁第一张纸后这个变量就变成了null,后续拾取的纸张根本没更新到这个变量里,而且投递系统和抓取系统完全脱节,没用到SimpleGrabSystem里的pickedItem引用。
修复步骤
- 关联抓取与投递系统:在
DepositPaper中获取SimpleGrabSystem的引用,直接使用当前持有的物品进行投递。 - 添加纸张标签判断:确保只有纸张能被投递,避免误操作其他物品。
- 更新投递逻辑:销毁纸张后清空抓取系统的引用,避免无效操作。
修改后的DepositPaper.cs代码:
using System.Collections; using System.Collections.Generic; using Unity.VisualScripting; using UnityEngine; using UnityEngine.InputSystem; using UnityEngine.SceneManagement; using TMPro; public class DepositPaper : MonoBehaviour { public int PaperCount = 0; public TextMeshPro paperText; public float raycastDistance = 100f; public LayerMask interactableLayer; // 引用抓取系统 private SimpleGrabSystem grabSystem; void Start() { // 获取玩家身上的抓取系统组件 grabSystem = GetComponent<SimpleGrabSystem>(); // 初始化文本显示 paperText.text = "Paper:" + PaperCount.ToString() + "/11"; } void Update() { Ray ray = new Ray(transform.position, transform.forward); if (Physics.Raycast(ray, out RaycastHit hit, raycastDistance, interactableLayer) && hit.collider.CompareTag("Printer")) { if(Input.GetKeyDown("e") && grabSystem.pickedItem != null) { // 判断当前持有的是纸张 if(grabSystem.pickedItem.CompareTag("Paper")) { // 销毁当前持有纸张 Destroy(grabSystem.pickedItem.gameObject); // 清空抓取系统的引用 grabSystem.pickedItem = null; PaperCount++; paperText.text = "Paper:" + PaperCount.ToString() + "/11"; } } } if(PaperCount == 2) { GameObject[] deadTaggedObjects = GameObject.FindGameObjectsWithTag("Dead_1"); foreach (GameObject deadtagged in deadTaggedObjects) { deadtagged.SetActive(false); } } } }
额外注意事项
- 给所有纸张对象添加
Paper标签,确保判断逻辑生效。 - 确保
DepositPaper和SimpleGrabSystem挂载在同一个玩家对象上,如果不在同一对象,可改用FindObjectOfType<SimpleGrabSystem>()获取引用。 - 移除原来的
Paper公共变量,因为已无需固定绑定对象。
内容的提问来源于stack exchange,提问作者Axton Gagnon
相关产品推荐
相关产品推荐

