Unity拾取物体脚本故障修复咨询:持有时物体不跟随手部、可无限触发投掷
Unity拾取物体脚本故障修复咨询:持有时物体不跟随手部、可无限触发投掷
嘿,我来帮你搞定这两个问题!咱们先拆解一下问题根源,再给你修复后的完整代码:
问题1:持有时物体不跟随手部
你的核心问题出在按键检测逻辑错误:原代码用了Input.GetKey(KeyCode.E)(按住E键才生效),而且在持有状态下,只要没按住E就会自动调用Drop()。这意味着你必须一直按住E才能拿住物体,松开就立刻掉落,自然没法让物体稳定跟随手部。
问题2:可无限触发投掷
原Throw()函数没有重置持有状态(isHolding没设为false,也没清空heldObject和heldRb),所以每次按F都会重复执行投掷逻辑,给物体持续加力,导致“无限扔”的情况。
修复后的完整代码
我把关键逻辑都调整好了,标注了修改点:
using TMPro; using Unity.VisualScripting; using UnityEngine; using static UnityEngine.GraphicsBuffer; public class PickUpObject : MonoBehaviour { [Header("Pickup")] public Transform hand; public float pickupDistance = 3f; public LayerMask pickupMask; [Header("UI")] [Header("Throw")] public float throwForce = 8f; // Throw force public ForceMode throwForceMode = ForceMode.VelocityChange; // Add force immediately GameObject heldObject; Rigidbody heldRb; bool isHolding; void Update() { // If holding something if (isHolding) { // 修改:用GetKeyDown(按下瞬间)触发放下,而不是松开E就自动放下 if (Input.GetKeyDown(KeyCode.E)) Drop(); // 修改:用GetKeyDown确保投掷只触发一次,不是按住F就一直扔 if (Input.GetKeyDown(KeyCode.F)) Throw(); return; } TryPickupRaycast(); } void TryPickupRaycast() { RaycastHit hit; if (Physics.Raycast( Camera.main.transform.position, Camera.main.transform.forward, out hit, pickupDistance, pickupMask)) { Rigidbody rb = hit.collider.GetComponent<Rigidbody>(); if (rb != null) { // 修改:用GetKeyDown(按下瞬间)触发拾取,不是按住E才拾取 if (Input.GetKeyDown(KeyCode.E)) { PickUp(hit.collider.gameObject, rb); } } } } void PickUp(GameObject obj, Rigidbody rb) { heldObject = obj; heldRb = rb; isHolding = true; heldRb.isKinematic = true; Collider col = obj.GetComponent<Collider>(); if (col) col.enabled = false; obj.transform.SetParent(hand); obj.transform.localPosition = Vector3.zero; obj.transform.localRotation = Quaternion.identity; } public void Drop() { if (!isHolding) return; isHolding = false; heldRb.isKinematic = false; Collider col = heldObject.GetComponent<Collider>(); if (col) col.enabled = true; heldObject.transform.SetParent(null); heldObject = null; heldRb = null; } void Throw() { if (!isHolding) return; // 修改:扔出前先启用碰撞体 Collider col = heldObject.GetComponent<Collider>(); if (col) col.enabled = true; // Unparent heldObject.transform.SetParent(null); // Reestablish the New Rigidbody Targetting if (heldObject != null) heldObject.SetActive(true); if (heldRb != null) { heldRb.isKinematic = false; // Throw force: at myHands.position.forward Vector3 dir = hand.forward; // restart speed and then addforce heldRb.linearVelocity = Vector3.zero; heldRb.angularVelocity = Vector3.zero; heldRb.AddForce(dir * throwForce, throwForceMode); } // 修改:清空持有状态,防止重复触发投掷 isHolding = false; heldObject = null; heldRb = null; } // Used by SceneTransform public bool IsHolding() => isHolding; public GameObject GetHeldObject() => heldObject; }
修复要点说明
- 按键逻辑修正:把所有
Input.GetKey改成Input.GetKeyDown,这样拾取、放下、投掷都是按下按键瞬间触发一次,符合正常操作逻辑。 - 投掷状态重置:在
Throw()函数末尾添加了持有状态的清空,确保扔出后不会重复执行投掷逻辑。 - 碰撞体管理:在投掷时主动启用碰撞体,和
Drop()保持一致,避免物体扔出后无法碰撞。
这样修改后,物体持有时会稳定跟随手部,按F只会投掷一次,不会无限触发啦!
备注:内容来源于stack exchange,提问作者idiotStackOverflow
相关产品推荐
相关产品推荐

