简体   繁体   中英

Issue with transform.position

I am trying to make a simple pong game where once the player or the enemy scores both of them get repositioned on the field.

I have this script on the enemy:

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

public class EnemyBehavior : MonoBehaviour
{
    Vector3 ballPosition;
    Vector3 paddlePosition;
    float movementSpeed = 0.1f;

    public Transform target;
    public float maxAngle = 35.0f;
    private Quaternion baseRotation;
    private Quaternion targetRotation;




    // Start is called before the first frame update
    void Start()
    {
        baseRotation = transform.rotation;
    }

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

        ballPosition = GameObject.Find("Ball").transform.position;
            paddlePosition = this.transform.position;


            if (paddlePosition.z < ballPosition.z)
            {
                paddlePosition.z += movementSpeed;
            }
            else if (paddlePosition.z > ballPosition.z)
            {
                paddlePosition.z -= movementSpeed;
            }
            transform.position = paddlePosition;

            Vector3 look = target.transform.position - transform.position;
            look.z = 0;

            Quaternion q = Quaternion.LookRotation(look);

            if (Quaternion.Angle(q, baseRotation) <= maxAngle)
            {
                targetRotation = q;
            }


            transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, Time.deltaTime * 2.0f);
        }
}

And then a goal script attached to the goal that looks like this:

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

public class Goal : MonoBehaviour
{
    public GameObject Ball;
    public GameObject Player;
    public GameObject Enemy;
    public Text Player2Score;
    public Text Player1Score;
    int Player2ScoreText = 0;
    int Player1ScoreText = 0;
    Rigidbody ballrig;
    Rigidbody playerrig;
    Rigidbody enemyrig;
    public ParticleSystem Particles;
    float timeLeft = 1.0f;
    public bool slowMo = false;
    // Start is called before the first frame update
    void Start()
    {
        ballrig = Ball.GetComponent<Rigidbody>();
        playerrig = Player.GetComponent<Rigidbody>();
        enemyrig = Enemy.GetComponent<Rigidbody>();

    }

    // Update is called once per frame
    void Update()
    {
        if (slowMo == true)
        {
            timeLeft -= Time.deltaTime;
            if (timeLeft < 0)
            {
                slowMo = false;
                timeLeft = 1.0f;
                Time.timeScale = 1f;
            }

        }
    }
    private void OnTriggerEnter(Collider other)
    {

        if (other.name == "Ball" && name == "Player_Goal")
        {
            slowMo = true;
            Time.timeScale = 0.5f;
            Explode();
            Player2ScoreText += 1;
            Player2Score.text = ("" + Player2ScoreText);
            Ball.transform.position = new Vector3(0f, 4f, 0f);
            Player.transform.position = new Vector3(-20f, 2f, 0f);
            Enemy.transform.position = new Vector3(20f, 2f, 0f);
            ballrig.velocity = Vector3.zero;
            ballrig.angularVelocity = Vector3.zero;
            playerrig.velocity = Vector3.zero;
            playerrig.angularVelocity = Vector3.zero;
            enemyrig.velocity = Vector3.zero;
            enemyrig.angularVelocity = Vector3.zero;
            int whoGetsIt = Random.Range(0, 2);
            if (whoGetsIt >= 1)
            {
                Vector3 Impulse = new Vector3(-10f, 5f, Random.Range(-10f, 10f));
                Ball.GetComponent<Rigidbody>().AddForce(Impulse, ForceMode.Impulse);
            }
            else
            {
                Vector3 Impulse = new Vector3(10f, 0f, Random.Range(-10f, 10f));
                Ball.GetComponent<Rigidbody>().AddForce(Impulse, ForceMode.Impulse);
            }

        }
        else if (other.name == "Ball" && name == "Enemy_Goal")
        {
            slowMo = true;
            Time.timeScale = 0.5f;
            Explode();
            Player1ScoreText += 1;
            Player1Score.text = ("" + Player1ScoreText);
            Ball.transform.position = new Vector3(0f, 4f, 0f);
            Player.transform.position = new Vector3(-20f, 2f, 0f);
            Enemy.transform.position = new Vector3(20f, 2f, 0f);
            ballrig.velocity = Vector3.zero;
            ballrig.angularVelocity = Vector3.zero;
            playerrig.velocity = Vector3.zero;
            playerrig.angularVelocity = Vector3.zero;
            enemyrig.velocity = Vector3.zero;
            enemyrig.angularVelocity = Vector3.zero;
            int whoGetsIt = Random.Range(0, 2);
            if (whoGetsIt >= 1)
            {
                Vector3 Impulse = new Vector3(-10f, 5f, Random.Range(-10f, 10f));
                Ball.GetComponent<Rigidbody>().AddForce(Impulse, ForceMode.Impulse);
            }
            else
            {
                Vector3 Impulse = new Vector3(10f, 0f, Random.Range(-10f, 10f));
                Ball.GetComponent<Rigidbody>().AddForce(Impulse, ForceMode.Impulse);
            }
        }
    }
    void Explode()
    {
        Particles.Play();
    }
}

Now the ball gets repositioned correctly after someone scores but for some reason the player and the enemy do not. Is it because they both have code in their update function so that code "overwrights" the repositioned command? And if so how can I get around that?

I can see that your players are using Rigidbody or Rigidbody2D .

Whenever a rigidbody is involved you should not set any position via transform but rather use the according rigidbody methods like MovePosition and MoveRotation or for directly setting them go through Rigibody.position and Rigidbody.rotation eg

....
    slowMo = true;
    Time.timeScale = 0.5f;
    Explode();
    Player2ScoreText += 1;
    Player2Score.text = ("" + Player2ScoreText);
    Ball.GetComponent<Rigidbody>().position = new Vector3(0f, 4f, 0f);
    Player.GetComponent<Rigidbody>().position = new Vector3(-20f, 2f, 0f);
    Enemy.GetComponent<Rigidbody>().position = new Vector3(20f, 2f, 0f);
    ballrig.velocity = Vector3.zero;
    ballrig.angularVelocity = Vector3.zero;
    playerrig.velocity = Vector3.zero;
    playerrig.angularVelocity = Vector3.zero;
    enemyrig.velocity = Vector3.zero;
    enemyrig.angularVelocity = Vector3.zero;
    int whoGetsIt = Random.Range(0, 2);
....

And then also in the EnemyBehaviour -> It should be FixedUpdate and look like

public Rigidbody target;

Rigidbody ball;
Rigidbody ownRigidbody;

void Start()
{
    baseRotation = transform.rotation;

    // Get reference only ONCE and store them1
    ball = GameObject.Find("Ball").GetComponent<Rigidbody>();
    ownRigidbody = GetComponent<Rigidbody>();
}

// Update is called once per frame
void FixedUpdate()
{
    ballPosition = ball.position;
    paddlePosition = ownRigidbody.position;

    if (paddlePosition.z < ballPosition.z)
    {
        paddlePosition.z += movementSpeed;
    }
    else if (paddlePosition.z > ballPosition.z)
    {
        paddlePosition.z -= movementSpeed;
    }
    ownRigidbody.MovePosition(paddlePosition;)

    Vector3 look = target.position - ownRigidbody.position;
    look.z = 0;

    Quaternion q = Quaternion.LookRotation(look);

    if (Quaternion.Angle(q, baseRotation) <= maxAngle)
    {
        targetRotation = q;
    }


    ownRigidbody.MoveRotation(Quaternion.Slerp(ownRigidbody.rotation, targetRotation, Time.deltaTime * 2.0f));
}

since here you want smooth interpolated position

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM