Unity中同脚本角色碰撞边界后全局禁用对应转向功能实现
问题场景与需求
- 游戏内存在多个相同的runner角色,初始仅第一个角色处于激活状态
- 激活角色按住鼠标左键时奔跑,松开则站立;当激活角色触碰未激活角色时,未激活角色会跟随其一同奔跑(参考Join Clash机制)
- 核心需求:当任意激活角色触碰场景左右两侧墙体时,禁用所有角色向该墙体方向的转向能力(转向通过鼠标左右移动实现)
解决方案
1. 全局边界状态管理
先创建一个全局管理器,统一跟踪左右墙体的碰撞状态,让所有角色共享这个状态:
using UnityEngine; public class BorderCollisionManager : MonoBehaviour { public static BorderCollisionManager Instance; public bool canTurnLeft = true; public bool canTurnRight = true; private void Awake() { if (Instance == null) Instance = this; else Destroy(gameObject); } // 触发碰撞时更新转向权限 private void OnTriggerEnter(Collider other) { if (other.CompareTag("LeftBorder")) canTurnLeft = false; else if (other.CompareTag("RightBorder")) canTurnRight = false; } // 离开碰撞时恢复转向权限 private void OnTriggerExit(Collider other) { if (other.CompareTag("LeftBorder")) canTurnLeft = true; else if (other.CompareTag("RightBorder")) canTurnRight = true; } }
配置说明:给左右墙体添加带Is Trigger的Collider,分别设置Tag为
LeftBorder和RightBorder;同时给激活角色的Collider勾选Is Trigger,确保能触发碰撞检测。
2. 修改角色移动旋转脚本
调整原StickmanMover的旋转逻辑,根据全局管理器的状态过滤无效方向的鼠标输入:
using UnityEngine; public class StickmanMover : MonoBehaviour { [SerializeField] private float _speedMoving; [SerializeField] private float _minRotation; [SerializeField] private float _maxRotation; // 修正原代码拼写错误:_maxRotatioan → _maxRotation [SerializeField] private float _maxSpeedMoving; [SerializeField] private float _speedRotationSide; [SerializeField] private float _speedRotationBack; private Rigidbody _rigidbody; private void Start() { _rigidbody = GetComponent<Rigidbody>(); } private void Update() { if (Input.GetKey(KeyCode.Mouse0)) { if (_rigidbody.velocity.magnitude < _maxSpeedMoving) { _rigidbody.AddForce(transform.forward * _speedMoving * Time.deltaTime); } // 过滤无效方向的鼠标输入 float mouseXInput = Input.GetAxis("Mouse X"); if (!BorderCollisionManager.Instance.canTurnLeft && mouseXInput < 0) { mouseXInput = 0; // 禁止向左转 } else if (!BorderCollisionManager.Instance.canTurnRight && mouseXInput > 0) { mouseXInput = 0; // 禁止向右转 } // 应用过滤后的输入执行旋转 transform.eulerAngles = new Vector3(0, transform.eulerAngles.y + mouseXInput * _speedRotationSide, 0); LimitRotation(); } if (!Input.GetKey(KeyCode.Mouse0)) { SetDefaultRotation(); } } private void LimitRotation() { Vector3 stickmanRotation = transform.rotation.eulerAngles; stickmanRotation.y = (stickmanRotation.y > 180) ? stickmanRotation.y - 360 : stickmanRotation.y; stickmanRotation.y = Mathf.Clamp(stickmanRotation.y, _minRotation, _maxRotation); transform.rotation = Quaternion.Euler(stickmanRotation); } private void SetDefaultRotation() { Quaternion rotation = Quaternion.LookRotation(Vector3.forward); transform.rotation = Quaternion.Lerp(transform.rotation, rotation, Time.deltaTime * _speedRotationBack); } }
3. 可选优化
- 如果角色有激活/未激活的状态切换逻辑,可在碰撞检测时判断角色是否激活,避免未激活角色触发边界状态变化
- 给
BorderCollisionManager添加事件委托,当转向权限变化时主动通知所有角色,减少每一帧的静态变量读取开销
内容的提问来源于stack exchange,提问作者user21403547
相关产品推荐
相关产品推荐

