unity character使用问题

unity 一直困扰我的问题,我在玩家角色使用character controller时候,剩下所有怪物都是碰撞体+刚体
如果有多个怪物例如10个20个,向你冲过来,如果一直冲,发生碰撞,这时候玩家特别容易跑到了怪物头顶
或者你像怪物移动的时候,也特别容易到怪物头顶。
我在设置character controller 尝试了修改所有参数,例如 限制斜度 偏移量 蒙皮 最小移动距离,哪怕改成0我都测试过了
还是不行,还是容易跑到怪物头顶上去,
我现在像请教如何解决这个问题?
1.不可以推荐我不使用character controller(我也会,不用你说,我需要的是用character controller如何解决)
2.怪物必须使用刚体+碰撞体,(不要给我提其他方法)
3.不要想着修改怪物移动逻辑,因为在运行当中会出现各种情况,一定会发生碰撞。(放弃你聪明的大脑在这个位置)
4.在只处理character controller这个前提下,如何解决这个问题

img

玩家代码非常简单

    private CharacterController _player;
    // Start is called before the first frame update
    void Start()
    {
        _player =  GetComponent<CharacterController>();
    }

    // Update is called once per frame
    void Update()
    {
        var horizontalInput = Input.GetAxis("Horizontal");
        var VerticalInput = Input.GetAxis("Vertical");
        var dir = new Vector3(horizontalInput, 0, VerticalInput).normalized;
        _player.SimpleMove(dir * (Time.deltaTime * 3000)); 
    }

怪物代码更简单,就是向玩家移动


```c#
    private Rigidbody _rigidbody;
    public Transform player;
    // Start is called before the first frame update
    void Start()
    {
        _rigidbody =  GetComponent<Rigidbody>();
    }

    // Update is called once per frame
    void Update()
    {
        var dir = ( player.position  - transform.position).normalized;
        _rigidbody.position = transform.position +  dir * Time.deltaTime  *  50f;
    }

重点:不要像大聪明一样,让我是用其他的控制器,不要像大聪明一样修改怪物逻辑

基于new bing部分指引作答:
根据您的要求,您可以尝试在Character Controller上使用一些附加的技巧来解决这个问题。以下是几种可能的解决方案:

1、使用Raycast检测碰撞:在Character Controller上使用Raycast来检测前方是否有碰撞物体。如果检测到碰撞物体,可以停止移动或采取其他适当的行动。这样可以避免角色穿过怪物。

void Update()
{
    var horizontalInput = Input.GetAxis("Horizontal");
    var verticalInput = Input.GetAxis("Vertical");
    var dir = new Vector3(horizontalInput, 0, verticalInput).normalized;
    
    RaycastHit hit;
    if (Physics.Raycast(transform.position, dir, out hit, 1f))
    {
        // 停止移动或采取其他适当的行动
    }
    else
    {
        _player.SimpleMove(dir * (Time.deltaTime * 3000));
    }
}

2、使用SphereCast检测碰撞:类似于上述的Raycast方法,您可以使用SphereCast来检测角色前方的碰撞物体。这对于检测更大范围的碰撞可能更有效。

void Update()
{
    var horizontalInput = Input.GetAxis("Horizontal");
    var verticalInput = Input.GetAxis("Vertical");
    var dir = new Vector3(horizontalInput, 0, verticalInput).normalized;
    
    RaycastHit hit;
    float sphereRadius = 0.5f; // 根据实际情况调整球体半径
    if (Physics.SphereCast(transform.position, sphereRadius, dir, out hit, 1f))
    {
        // 停止移动或采取其他适当的行动
    }
    else
    {
        _player.SimpleMove(dir * (Time.deltaTime * 3000));
    }
}

这些方法可以帮助您在使用Character Controller时避免角色穿过怪物。您可以根据实际需求调整射线或球体的参数以获得最佳结果。请注意,这些解决方案可能需要根据您的场景和需求进行进一步调整和优化。


1. 将Player的Collider大小缩小为不与Monster重叠。
2. 使用`CharacterController.Move()`替换`CharacterController.SimpleMove()`。
3. 在`CharacterController.Move()`之后,使用`Physics.SphereCast()`或`Physics.CapsuleCast()`检测玩家与怪物之间是否有障碍物,若有,则向移动方向施加反向力以避免穿透。
修改你上面提供的代码:

private CharacterController _player;
private Vector3 _moveDirection = Vector3.zero;

public float playerSpeed = 5f;

public float castRadius = 1f;
public float castDistance = 1f;

void Start()
{
    _player = GetComponent<CharacterController>();
}

void Update()
{
    var horizontalInput = Input.GetAxis("Horizontal");
    var VerticalInput = Input.GetAxis("Vertical");

    _moveDirection = new Vector3(horizontalInput, 0, VerticalInput).normalized;
    _moveDirection *= playerSpeed;

    // 计算玩家的新位置
    _player.Move(_moveDirection * Time.deltaTime);

    // 检测是否有障碍物
    RaycastHit hit;
    if (Physics.SphereCast(transform.position, castRadius, _moveDirection, out hit, castDistance))
    {
        Vector3 reflectDirection = Vector3.Reflect(_moveDirection, hit.normal);
        _player.Move(reflectDirection * Time.deltaTime);
    }
}
使用了`SphereCast()`函数来检测玩家与怪物之间是否有障碍物,如果有,则进行反向操作以避免穿透。