将 Transform.position 与碰撞器一起使用

问题描述 投票:0回答:1

所以我用transform.position编写了我的运动,我不想使用刚体,因为我使用我自己的物理计算。作为回报,我只会引入额外的步骤(我什至不需要,因为我基本上将所有内容都清空了,而且它会引入新的错误(例如在我的斜坡运动中)......所以,我需要一些限制我可能的东西移动方向,受限于我的对撞机的命中位置,我正在考虑光线投射,这会起作用...但我必须拍摄太多的光线投射,并且无论如何都不是万无一失的,即使它是 8 个方向的光线投射...有人对我的问题有任何想法或解决方案吗?

代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Movement : MonoBehaviour
{
    [Header("Player")]
    public float PlayerHeight = 2f;

    [Header("Objects")]
    public Transform Direction;

    // Input
    float CurrentMoveX;
    float CurrentMoveZ;

    float TargetMoveX;
    float TargetMoveZ;

    [Header("Settings")]
    public float CurrentMoveSpeedMode = 5f;

    [Header("Movement Physics")]
    public float AccelSpeed = 4.5f;
    public float DeaccelSpeed = 4.5f;
    public float SnapRange = 0.01f;

    [Header("Gravity Physics")]
    public float GravityStrength = 1f;

    [Header("Ground")]
    public float GroundDetectionRadius = 0.3f;
    bool IsGrounded;

    // Units
    float GForce = 9.80665f;
    float SpeedConversionValue = 3.6f;

    // Direction
    Vector3 MoveDirection;

    // Vertical
    float CurrentVerticalVelocity;

    void Update()
    {
        HorizontalMovement();
        MoveOutput(); 
    }
    void HorizontalMovement()
    { 
         InputDirection();
         EditedDirection();
         Ground();
    }
    void InputDirection()
    { 
        // Move X - Horizontal
        if(Input.GetAxisRaw("Horizontal") < 0f)
        { 
            TargetMoveX = -CurrentMoveSpeedMode / SpeedConversionValue;

            if(CurrentMoveX > TargetMoveX)
            { 
                if(CurrentMoveX > 0f)
                { 
                    CurrentMoveX -= GForce * (AccelSpeed + DeaccelSpeed) * Time.deltaTime;
                }
                else if(CurrentMoveX <= 0f)
                { 
                    CurrentMoveX -= GForce * AccelSpeed * Time.deltaTime;
                }           
            }
            else if(CurrentMoveX <= TargetMoveX)
            {
                CurrentMoveX = TargetMoveX;
            }
        }
        else if(Input.GetAxisRaw("Horizontal") > 0f)
        { 
            TargetMoveX = CurrentMoveSpeedMode / SpeedConversionValue;

            if(CurrentMoveX < TargetMoveX)
            { 
                if(CurrentMoveX < 0f)
                { 
                    CurrentMoveX += GForce * (AccelSpeed + DeaccelSpeed) * Time.deltaTime;
                }
                else if(CurrentMoveX >= 0f)
                { 
                    CurrentMoveX += GForce * AccelSpeed * Time.deltaTime;
                }                
            }
            else if(CurrentMoveX >= TargetMoveX)
            {
                CurrentMoveX = TargetMoveX;
            }
        }
        else if(Input.GetAxisRaw("Horizontal") == 0f)
        { 
            TargetMoveX = 0f;

            if(CurrentMoveX > 0.1f)
            { 
                CurrentMoveX -= GForce * (AccelSpeed + DeaccelSpeed) * Time.deltaTime;
            }
            else if(CurrentMoveX < -0.1f)
            { 
                CurrentMoveX += GForce * AccelSpeed * Time.deltaTime;
            }
            else
            { 
                CurrentMoveX = TargetMoveX;
            }
        }

        // Move Z - Vertical
        if(Input.GetAxisRaw("Vertical") < 0f)
        { 
            TargetMoveZ = -CurrentMoveSpeedMode / SpeedConversionValue;

            if(CurrentMoveZ > TargetMoveZ)
            { 
                if(CurrentMoveZ > 0f)
                { 
                    CurrentMoveZ -= GForce * (AccelSpeed + DeaccelSpeed) * Time.deltaTime;
                }
                else if(CurrentMoveZ <= 0f)
                { 
                    CurrentMoveZ -= GForce * AccelSpeed * Time.deltaTime;
                }           
            }
            else if(CurrentMoveZ <= TargetMoveZ)
            {
                CurrentMoveZ = TargetMoveZ;
            }
        }
        else if(Input.GetAxisRaw("Vertical") > 0f)
        { 
            TargetMoveZ = CurrentMoveSpeedMode / SpeedConversionValue;

            if(CurrentMoveZ < TargetMoveZ)
            { 
                if(CurrentMoveZ < 0f)
                { 
                    CurrentMoveZ += GForce * (AccelSpeed + DeaccelSpeed) * Time.deltaTime;
                }
                else if(CurrentMoveZ >= 0f)
                { 
                    CurrentMoveZ += GForce * AccelSpeed * Time.deltaTime;
                }                
            }
            else if(CurrentMoveZ >= TargetMoveZ)
            {
                CurrentMoveZ = TargetMoveZ;
            }
        }
        else if(Input.GetAxisRaw("Vertical") == 0f)
        { 
            TargetMoveZ = 0f;

            if(CurrentMoveZ > SnapRange)
            { 
                CurrentMoveZ -= GForce * (AccelSpeed + DeaccelSpeed) * Time.deltaTime;
            }
            else if(CurrentMoveZ < -SnapRange)
            { 
                CurrentMoveZ += GForce * AccelSpeed * Time.deltaTime;
            }
            else
            { 
                CurrentMoveZ = TargetMoveZ;
            }
        }
    }
    void EditedDirection()
    { 
        // Directionalize And Normalize Movement Input
        Vector3 DirectionInput = Direction.forward * CurrentMoveZ + Direction.right * CurrentMoveX;
        Vector3 DirectionNormal = DirectionInput.normalized;
                DirectionNormal = new Vector3(Mathf.Abs(DirectionNormal.x), 0, Mathf.Abs(DirectionNormal.z));
        Vector3 OutputDirection = new Vector3(DirectionInput.x * DirectionNormal.x, 0, DirectionInput.z * DirectionNormal.z);


        // Slope Detection
        RaycastHit TerrainHit;

        if(Physics.SphereCast(transform.position, PlayerHeight / 4f, Vector3.down, out TerrainHit))
        {
            if(TerrainHit.normal != Vector3.up)
            { 
                OnSlopeFunction();     
            }
            else
            { 
                NotOnSlopeFunction();
            }
        }
        else
        { 
            NotOnSlopeFunction();
        }

        // Follow Terrain/Slopes

        void OnSlopeFunction()
        { 
            MoveDirection = Vector3.ProjectOnPlane(OutputDirection, TerrainHit.normal);             
        }
        void NotOnSlopeFunction()
        { 
            MoveDirection = OutputDirection;
        }
    }
    void Ground()
    { 
        // Prevent Clipping Through Floor (Especially when moving down slopes)

        GroundAlign();            

        void GroundAlign()
        {
            RaycastHit GroundAlignHit;
            
            if(Physics.Raycast(transform.position, Vector3.down, out GroundAlignHit, PlayerHeight / 2f))
            { 
                Vector3 GroundAlignPos = GroundAlignHit.point;
                transform.position = new Vector3(transform.position.x, GroundAlignPos.y + PlayerHeight / 2f, transform.position.z);
            }
        }
    }

    void MoveOutput()
    { 
        // Output Movement
        transform.position = MoveDirection * Time.deltaTime;
    }
}

Rigidbody,预计运动正常运行,似乎不是结果,transform.position也似乎更平滑,因为它不需要计算物理,它基于自定义物理值,存储在浮点数中。

unity-game-engine unityscript
1个回答
0
投票

无需过多关注,我就会切入您的

MoveOutput
功能。假设您的对撞机只是一个基元,您可以在应用新位置之前使用
Physics.OverlapCapsule
(立方体和球体也可用)检查“重叠”。

void MoveOutput()
{
    Vector3 newPos = transform.position + MoveDirection * Time.deltaTime;
    //TODO adjust parameters to your needs
    //NOTE the capsule is always upright no matter how your object is rotated
    float height = 2;
    if(Physics.OverlapCapsule(newPos - (height / 2) * Vector3.up, newPos + (height / 2) * Vector3.up, 0.5f).Length == 0)
    {
        transform.position = newPos;
    }
}

该密码将阻止您进入墙壁。如果您以一定角度进入,您将不会滑行。

请注意,帧速率下降可能会导致一些卡顿,从而导致您出界或卡住。我强烈建议您将

Update
更换为
FixedUpdate
,以获得更高的一致性。

© www.soinside.com 2019 - 2024. All rights reserved.