Unity中void Update()内分步执行轨道跟随代码的问题咨询
It looks like your issue comes from running both the MoveTowards and rotation logic every frame simultaneously in Update(). That's why the ball jumps straight to P1 and starts rotating right away—both actions are fighting to set the position on the first frame.
To fix this, we need to add a state system to control which phase the ball is in: first moving to P1, then starting the rotation once it's arrived. Here's how to implement it step by step:
Step 1: Add a State Tracker
First, define a simple enum to track the current phase of the ball's movement. This keeps our logic clean and easy to extend if you add more steps later.
Step 2: Modify the Update Loop
Update the Update() method to only run the logic for the current state. Once the ball reaches P1, switch to the rotation state.
Full Modified Code
using UnityEngine; public class BallController : MonoBehaviour { Rigidbody rigidbody; public GameObject ball; Vector3 P1 = new Vector3(-5, 1.5f, 25); public float theta; // Enum to track our current state private enum BallState { MovingToP1, Rotating } private BallState currentState = BallState.MovingToP1; // Small threshold to check if we've reached P1 (adjust based on your needs) private float positionThreshold = 0.1f; void Start() { rigidbody = GetComponent<Rigidbody>(); } void Update() { switch(currentState) { case BallState.MovingToP1: // Move towards P1 each frame ball.transform.position = Vector3.MoveTowards(ball.transform.position, P1, 0.05f); // Check if we're close enough to P1 if(Vector3.Distance(ball.transform.position, P1) < positionThreshold) { // Snap to P1 exactly (optional but clean) ball.transform.position = P1; // Switch to rotation state currentState = BallState.Rotating; } break; case BallState.Rotating: // Run rotation logic only after moving is done if(theta < 210) { theta += 1; ball.transform.position = Rot(theta); } break; } } Vector3 Rot(float theta) // rotation by trigonometric equations { Vector3 P2; P2.x = (3 * Mathf.Cos(theta * Mathf.PI / 180) - 3 * Mathf.Sin(theta * Mathf.PI / 180)) -8; P2.y = 1.5f; P2.z = (3 * Mathf.Sin(theta * Mathf.PI / 180) + 3 * Mathf.Cos(theta * Mathf.PI / 180)) + 22 ; return P2; } }
Key Fixes Explained
- State Control: The
BallStateenum ensures only one action runs at a time. No more conflicting position updates. - Position Check: Using
Vector3.Distance(orVector3.SqrMagnitudefor better performance, since it avoids square root) lets us detect when the ball has reached P1. We use a small threshold instead of checking for exact equality because floating-point positions are rarely perfectly precise. - Clean Transition: Once the ball arrives, we snap it to P1 (optional but prevents tiny jitters) and switch to the rotation phase.
Optional Optimization
For better performance, replace Vector3.Distance with Vector3.SqrMagnitude because calculating square roots is expensive:
if((ball.transform.position - P1).sqrMagnitude < positionThreshold * positionThreshold)
Just make sure to square your threshold value to match!
内容的提问来源于stack exchange,提问作者BaNya

