You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 18:05:38