角色不会与Unity3D中的其他对象发生碰撞

时间:2015-05-09 14:18:46

标签: unity3d

我现在正在玩游戏(第一款3D风格的游戏),我的角色碰撞有问题。我有一个Player对象,它有另一个对象作为真正的可移动字符(现在我只有一个)。我的刚性和箱式对撞机太贴在我的角色上了。我已经制作了一个级别(使用手动放置的平台),我想避免我的平台掉落的特性,而用户控制它。我曾尝试在平台的一侧放置一个立方体,并在其上安装了盒子对撞机,但由于某些原因,角色没有检测到碰撞。我希望我的角色被对撞机" cube"停止,但它不会发生。

我使用此脚本移动我的对象(附加到我的角色Player对象):

public class Bounce : MonoBehaviour {


float lerpTime;
float currentLerpTime;
float perc = 1;

Vector3 startPos;
Vector3 endPos;

bool firstInput;
public bool justJump;

public GameObject player;


// Update is called once per frame
void Update () {
    if (Input.GetButtonDown("up") || Input.GetButtonDown("down") || Input.GetButtonDown("left") || Input.GetButtonDown("right")) {
        if (perc == 1) {
            lerpTime = 1;
            currentLerpTime = 0;
            firstInput = true;
            justJump = true;
        }
    }
    startPos = gameObject.transform.position;


    if (Input.GetButtonDown("up") && gameObject.transform.position == endPos) {
        endPos = transform.position + player.transform.rotation * (new Vector3(0, 0, 1f));

    }
    if (Input.GetButtonDown("down") && gameObject.transform.position == endPos) {
        endPos = transform.position + player.transform.rotation * (new Vector3(0, 0, -1f));
    }

    if (firstInput == true) {
        currentLerpTime += Time.deltaTime * 5;
        perc = currentLerpTime / lerpTime;
        gameObject.transform.position = Vector3.Lerp(startPos, endPos, perc);
        if (perc > 0.8f)  {
            perc = 1;
        }

        if (Mathf.Round(perc) == 1) {
            justJump = false;
        }
    }


}

void OnCollisionEnter(Collision collision) {
    Debug.Log("!!!!!!!");
}
}

我在角色本身使用这个脚本:(旋转和动画)

代码(csharp):

public class AnimationController : MonoBehaviour {

Animator anim;
public GameObject thePlayer;

// Use this for initialization
void Start () {
    anim = gameObject.GetComponent<Animator>();
}

// Update is called once per frame
void Update () {
    Bounce bounceScript = thePlayer.GetComponent<Bounce>();
    if (bounceScript.justJump == true) {
        anim.SetBool("Jump", true);
    }
    else {
        anim.SetBool("Jump", false);
    }

    if (Input.GetButtonDown("right")) {
        //transform.rotation *= Quaternion.Euler(0,30,0);
        transform.RotateAround(transform.position, Vector3.up, 90);
    }
    if (Input.GetButtonDown("left")) {
        transform.Rotate (0, -90, 0, 0);
    }
}
}

只有当立方体不是运动时它才会发生碰撞,但它并不能阻止我的玩家因某种原因通过立方体。

我已经阅读了一些有关此类问题的网站,但没有任何帮助。

如果你能给我任何代码改进,那就太好了。)

EDIT1:

很抱歉,为了回答这么晚,过去几天我的游戏无法做任何事情。今天我尝试用光线投射做一些事情,你可以看到我的代码,我第一次尝试只是在更新方法中:

void Update () {
        if (Input.GetButtonDown("up") || Input.GetButtonDown("down") || Input.GetButtonDown("left") || Input.GetButtonDown("right")) {
            if (perc == 1) {
                lerpTime = 1;
                currentLerpTime = 0;
                firstInput = true;
                justJump = true;
            }
        }
        startPos = gameObject.transform.position;

    /*  if (Input.GetButtonDown("right") && gameObject.transform.position == endPos) {
            //endPos = new Vector3(transform.position.x + 0.5f, transform.position.y, transform.position.z);

        }
        if (Input.GetButtonDown("left") && gameObject.transform.position == endPos) {
            endPos = new Vector3(transform.position.x - 0.5f, transform.position.y, transform.position.z);
        }*/


        Vector3 fwd = player.transform.TransformDirection(Vector3.forward);
        RaycastHit objectHit;

        if (Physics.Raycast(player.transform.position, fwd, out objectHit, 2)) {
            if (objectHit.collider.tag == "Wall") {
                Debug.Log("WALL RAYCAST HIT!");
            }
        }


        if (Input.GetButtonDown("up") && gameObject.transform.position == endPos) {
            endPos = transform.position + player.transform.rotation * (new Vector3(0, 0, 1f));

        }
        if (Input.GetButtonDown("down") && gameObject.transform.position == endPos) {
            //endPos = transform.position + player.transform.rotation * (new Vector3(0, 0, -1f)); 
        }


        if (firstInput == true) {
                currentLerpTime += Time.deltaTime * 5;
                perc = currentLerpTime / lerpTime;
                gameObject.transform.position = Vector3.Lerp(startPos, endPos, perc);
                if (perc > 0.8f)  {
                    perc = 1;
                }

                if (Mathf.Round(perc) == 1) {
                    justJump = false;
                }
            }
    }

有了这个,我可以一次2-3次调试日志WALL RAYCAST HIT,但只有一次。当我移动角色时,由于某种原因它不会再次出现(我认为应该因为在每一帧中调用更新方法)。

虽然当我将它放在Input.GetButtonDown(&#34; up&#34;)方法中时,它不会记录任何内容:

if (Input.GetButtonDown("up") && gameObject.transform.position == endPos) {
             fwd = player.transform.TransformDirection(Vector3.forward);


            if (Physics.Raycast(player.transform.position, fwd, out objectHit, 2)) {
                if (objectHit.collider.tag == "Wall") {
                    Debug.Log("WALL RAYCAST HIT!");
                }
            }
            endPos = transform.position + player.transform.rotation * (new Vector3(0, 0, 1f));

        }

2 个答案:

答案 0 :(得分:0)

当你更新transform.position时,你实际上是&#34;传送&#34;你反对新的立场。即使你顺利地使用像Lerp函数这样的东西,就像你在移动脚本上那样,Unity也知道你将对象传送到新的坐标。

这没错,所有游戏都是这样的。像Lerp这样的功能只是创造了运动的幻觉,所以玩家就像实际从一个点移动到另一个点的角色一样。

正在发生的事情是,尽管路径上有任何对象,但您的脚本仍会告诉角色移动到新位置。碰撞发生,但你的更新功能仍然将角色置于新的位置。

我可以想到两种可能的解决方法:

  1. 为Move脚本创建一个 OnCollisionEnter()函数,以某种方式阻止您的移动。通过像 firstInput 那样创建标记,您可以实现此目的。

  2. 您可以使用刚体来处理移动和碰撞,而不是更新您的transform.position。这样,每当你需要移动角色时,你需要为角色刚体添加一些速度,而不是直接更新transform.position。

  3. 因为你的角色不会以一种恒定的方式移动,而是一次一步地移动#34;方式,我认为第一个解决方案更适合你。

    代码将是这样的

    void OnCollisionenter(Collision collision)
    {
        collided = true;
    }
    

    并且Move脚本的结尾应更新为

    if(!collided)
    {
        if (firstInput == true) {
            currentLerpTime += Time.deltaTime * 5;
            perc = currentLerpTime / lerpTime;
            transform.position = Vector3.Lerp(startPos, endPos, perc);
            if (perc > 0.8f)  {
                perc = 1;
            }
    
            if (Mathf.Round(perc) == 1) {
                justJump = false;
            }
        }
    }
    else
    {
        // Remember to reset this when you stop your character
        endPos = transform.position;
        collided = false;
    }
    

    这次我在编写代码之前无法测试代码,因此您可能需要在工作之前进行一些更改。

    ps:我认为您不需要 firstInput 变量。一旦设置为true,您再也不会将其设置为false。此外, Input.GetButtonDown()函数仅在按下按钮的第一帧时返回true,这就是我在您创建 firstInput 时的预期。

    ps2:我的解决方案为您的班级添加了碰撞布尔属性,因此不要忘记添加一行private bool collided;与您的其他类属性。另外,请阅读关于我在其他问题上推荐您的状态机模式的章节。创建这种控制属性suach作为碰撞布尔值不是一个好习惯,如果你已经实现了状态机,这可以避免。

答案 1 :(得分:0)

嘿,我有一个类似的问题,我使用Mixamo.com的动画模型,我注意到,由于一些奇怪的原因,角色没有碰撞边界,尽管有对撞机,由于某种原因,它直到我添加后才起作用一个 CharacterController 到我的模型而不是碰撞器只是搜索CharacterController并添加它,就像你将任何脚本或刚体添加到你的游戏对象一样。

希望它有效XD问候