Почему возникает это странное дрожание?

У меня есть сцена, в которой игрок может поднимать и бросать предметы, а также двигаться и осматриваться.

Все объекты игроков являются дочерними элементами пустого игрового объекта «MainCharacter»:

MainCharacter >
    Capsule (With RigidBody and PlayerMoveScript) >
        PlayerBase (empty - used for checking if grounded)
        MainCamera >
            Hands(With PickUpDrop script)

Объект, который я подбираю, перемещается в мои руки, однако после того, как моя капсула сталкивается с какими-либо стенами, возникает странное дрожание, которое я не могу понять, как исправить!!

Вот .exe: GameTest Вот папка с данными: Данные

Вот скрипты:

Сценарий «Возьми и брось»:

public bool handsFull = false;

    public float distanceMax = 20f;

    public Transform handPosition;

    public LayerMask canPickUp;

    public GameObject taggedGameObject;

    public bool colliderTriggered;

    public bool bounds;

    public PickedUpObject pickedUpScript;

    public Rigidbody player;

    // Use this for initialization
    void Start () {

        print(FindClosestPickup().name);
        handPosition = transform;
        pickedUpScript = null;

    }

    // Update is called once per frame
    void Update () {


                if (Input.GetKeyDown (KeyCode.E) && !bounds) {
                        if (Physics.CheckSphere (handPosition.position, 2f, canPickUp)) {

                                if (handsFull) {
                                        Drop ();
                                }

                                if (!handsFull) {
                                        PickedUp ();
                                }

                handsFull = !handsFull;

                        }
                }

                if (handsFull) {
                        RotateMovePickedUpObject();
                }   


        }



    private void PickedUp(){

        //Closest object to top of list
        taggedGameObject = (GameObject)FindClosestPickup();

        taggedGameObject.collider.isTrigger = true;



        taggedGameObject.rigidbody.useGravity = false;
        taggedGameObject.rigidbody.isKinematic = true;

        pickedUpScript = taggedGameObject.GetComponent<PickedUpObject> ();

        Debug.Log ("Pick Up");


    }

    private void RotateMovePickedUpObject(){

        //Rotate

        if(Input.GetKeyDown(KeyCode.End)){
            taggedGameObject.transform.localRotation *= Quaternion.Euler(0, 0, 45);
        }
        if(Input.GetKeyDown(KeyCode.Delete)){
            taggedGameObject.transform.localRotation *= Quaternion.Euler(0, 45, 0);
        }
        if(Input.GetKeyDown(KeyCode.PageDown)){
            taggedGameObject.transform.localRotation *= Quaternion.Euler(0, -45, 0);
        }
        if(Input.GetKeyDown(KeyCode.Home)){
            taggedGameObject.transform.localRotation *= Quaternion.Euler(0, 0, -45);
        }
        if(Input.GetKeyDown(KeyCode.PageUp)){
            taggedGameObject.transform.localRotation *= Quaternion.Euler(-45, 0, 0);
        }
        if(Input.GetKeyDown(KeyCode.Insert)){
            taggedGameObject.transform.localRotation *= Quaternion.Euler(45, 0, 0);
        }

        taggedGameObject.transform.position = Vector3.Lerp(taggedGameObject.transform.position, handPosition.position, (1 - Mathf.Exp( -20 * Time.smoothDeltaTime )) * 10);

    }


    private void Drop(){

        taggedGameObject.collider.isTrigger = false;

        taggedGameObject.rigidbody.useGravity = true;
        taggedGameObject.rigidbody.isKinematic = false;

        taggedGameObject = null;

        Debug.Log ("Drop");

        pickedUpScript = null;

    }

    private GameObject FindClosestPickup() {

        //Find closest gameobject with tag
        GameObject[] gos;
        gos = GameObject.FindGameObjectsWithTag("pickup");
        GameObject closest = null;
        float distance = Mathf.Infinity;
        Vector3 position = transform.position;

        foreach (GameObject go in gos) {
            Vector3 diff = go.transform.position - position;
            float curDistance = diff.sqrMagnitude;
            if (curDistance < distance) {
                closest = go;
                distance = curDistance;
            }
        }

        return closest;
    }

}

Скрипт поднятых предметов:

public PickUpDrop pickUpScript;
    public GameObject thisOne;
    public Color thecolor;
    public bool inObject;

    // Use this for initialization
    void Start () {
        thisOne = this.gameObject;
    }

    // Update is called once per frame
    void Update () 
    {
        thecolor = thisOne.renderer.material.color;

    if (pickUpScript.taggedGameObject != thisOne)
        {
            gameObject.renderer.material.color = Color.gray;
        }

    if (pickUpScript.taggedGameObject == thisOne)
        {
            Color color = renderer.material.color;
            color.a = 0.5f;
            renderer.material.color = color;
        }
    }

    void OnTriggerEnter ()
    {
        if (thisOne == pickUpScript.taggedGameObject)
        {
            inObject = true;
            pickUpScript.bounds = true;
            gameObject.renderer.material.color = Color.red;

        }
    }

    void OnTriggerExit()
    {
        if(thisOne == pickUpScript.taggedGameObject)
        {
            inObject = false;
            pickUpScript.bounds = false;
            gameObject.renderer.material.color = Color.gray;        
        }
    }

}

person user3902259    schedule 01.09.2014    source источник
comment
Я не отлаживал ваш код, но заметил, что у вас есть метод GameObject FindClosestPickup(). Если имеется несколько одинаково близких объектов, то объект, возвращаемый методом, может быть нестабильным из-за плавающей запятой. ошибки. Нестабильность может привести к флип-флопам, поскольку метод возвращает разные объекты при каждом обновлении игры. Может быть здесь дело в этом?   -  person dbc    schedule 01.09.2014
comment
Я сомневаюсь, что это причина, мои объекты находятся далеко друг от друга, и дрожание все еще происходит только с одним объектом, но спасибо за предупреждение в будущем!   -  person user3902259    schedule 02.09.2014


Ответы (1)


taggedGameObject.transform.position = Vector3.Lerp(taggedGameObject.transform.position, handPosition.position, (1 - Mathf.Exp( -20 * Time.smoothDeltaTime )) * 10);

Эта линия будет продолжать перемещать объект к положению руки. Если у вас есть твердое тело, прикрепленное к игровому объекту, который вы перемещаете, то физика, действующая на этот объект во время расчета физики, будет конфликтовать с ручным перемещением объекта во время функции обновления.

Решение зависит от того, что вы хотите, чтобы произошло, когда возникнет этот конфликт. Если вы просто хотите, чтобы «дрожание» прекратилось, и вы по-прежнему могли удерживать объекты против других физических объектов, используйте это;

taggedGameObject.rigidbody.AddForce( ( taggedGameObject.transform.position - handPosition.position ) * force );

Это сохранит все взаимодействия с твердым телом. Вам придется настроить силу, с которой вы перемещаете объект, и, возможно, отключить гравитацию на отмеченном игровом объекте, пока он находится в руках игроков. Но это должно дать желаемый эффект.

person Josh    schedule 02.09.2014
comment
Привет! Спасибо за помощь, скрипт в основном работает! (Мне пришлось изменить расчет на (handPosition.position -taggedGameObject.transform.position)) Я временно решил проблему с пружинным соединением, однако это исправление позволило мне решить проблему гораздо более эффективным способом! Спасибо еще раз! - person user3902259; 02.09.2014