协程不会让步
Coroutine Won't Yield
我想不通为什么这个协程不会让步。
这段代码...
while(angle > 1.0f)
{
my_transform.rotation = Quaternion.Slerp(my_transform.rotation, fwdRotation, Time.deltaTime * 2.0f);
angle = Quaternion.Angle(my_transform.rotation, fwdRotation);
Debug.Log ("Inside loop" + angle);
yield return null;
}
...不会屈服。它只是通过它。我知道它确实如此,因为在 运行 时间里,我一帧一帧地玩游戏,我可以看到这行代码...
yield return StartCoroutine(MoveBall(col));
rigidbody.WakeUp(); <<<<<<-------THIS ONE RIGHT HERE
...旋转调整完成前执行。为什么会发生这种情况?
using UnityEngine;
using System.Collections;
public class EmptyBall : MonoBehaviour
{
public Ball.BallTypes this_ball_type;
public PlayerCharacter this_player;
public AudioClip capture_attempt;
public AudioClip attempting_capture;
public AudioClip capture_success;
public AudioClip capture_fail;
public GameObject capture_orb_prefab;
private Transform my_transform;
private RaycastHit hit;
private float distance_to_ground;
private CalculateCapture calculate_capture_script = new CalculateCapture();
void Start()
{
my_transform = transform;
}
void Update()
{
if(Physics.Raycast(transform.position, -Vector3.up, out hit)){
distance_to_ground = hit.distance;
}
}
void OnCollisionEnter(Collision col)
{
if(col.gameObject.tag == "Capturable")
{
Monster this_monster = col.gameObject.GetComponent<Monster>();
if(!this_monster.is_captured)
{
audio.PlayOneShot(capture_attempt);
col.gameObject.GetComponent<Animation>().enabled = false;
StartCoroutine(Capture(col));
}
else
{
}
}
else
{
Destroy(this.gameObject);
}
}
private IEnumerator Capture(Collision col)
{
yield return StartCoroutine(MoveBall(col));
rigidbody.WakeUp();
while(distance_to_ground > 0.2f)
{
yield return null;
}
rigidbody.isKinematic = true;
yield return StartCoroutine(TryToCatch(col));
}
private IEnumerator MoveBall(Collision col)
{
Vector3 move_to = new Vector3(transform.position.x-1.5f, col.contacts[0].point.y+1.5f, transform.position.z-1.5f);
while(Vector3.Distance(transform.position, move_to) > 0.01f)
{
rigidbody.velocity = Vector3.zero;
rigidbody.angularVelocity = Vector3.zero;
rigidbody.Sleep();
transform.LookAt(col.transform.position);
transform.position = Vector3.Lerp(transform.position, move_to, 5f * Time.deltaTime);
yield return null;
}
animation["Open_Top"].speed = 5;
animation.Play("Open_Top");
GameObject orb = Instantiate(capture_orb_prefab, col.gameObject.GetComponentInChildren<Renderer>().renderer.bounds.center, Quaternion.identity) as GameObject;
col.gameObject.SetActive(false);
while(Vector3.Distance(my_transform.position, orb.transform.position) > 0.01f)
{
Vector3 orb_target = new Vector3(my_transform.position.x, my_transform.position.y, my_transform.position.z);
orb.transform.position = Vector3.Lerp(orb.transform.position, orb_target, 2.7f * Time.deltaTime);
yield return null;
}
orb.transform.parent = my_transform;
animation["Close_Top"].speed = -5f;
animation["Close_Top"].time = animation["Close_Top"].length;
animation.Play("Close_Top");
Vector3 flatFwd = new Vector3(my_transform.forward.x, 0, my_transform.forward.z);
Quaternion fwdRotation = Quaternion.LookRotation(flatFwd, Vector3.up);
float angle = Quaternion.Angle(my_transform.rotation, fwdRotation);
Debug.Log (angle);
while(angle > 1.0f)
{
my_transform.rotation = Quaternion.Slerp(my_transform.rotation, fwdRotation, Time.deltaTime * 2.0f);
angle = Quaternion.Angle(my_transform.rotation, fwdRotation);
Debug.Log ("Inside loop" + angle);
yield return null;
}
Destroy(orb);
yield return null;
}
private IEnumerator TryToCatch(Collision col)
{
Monster this_monster = col.gameObject.GetComponent<Monster>();
audio.PlayOneShot(attempting_capture);
yield return new WaitForSeconds(attempting_capture.length+1);
bool try_to_capture = calculate_capture_script.AttemptCapture(this_monster.status_condition, this_ball_type, this_monster.cur_hp,
this_monster.cur_max_hp, this_monster.capture_rate);
if(try_to_capture){
this_monster.is_captured = true;
this_monster.trainers_name = this_player.players_name;
Monster temp = this_monster;
PlayerMonsterData data_holder_monster = new PlayerMonsterData (temp.is_setup, temp.is_captured, temp.trainers_name, temp.monster_name,
temp.nick_name,
temp.is_from_trade, temp.level, temp.gender, temp.nature, temp.max_hp,
temp.cur_max_hp, temp.max_atk, temp.max_def, temp.max_spatk, temp.max_spdef,
temp.max_spd, temp.cur_hp, temp.cur_atk, temp.cur_def, temp.cur_spatk,
temp.cur_spdef, temp.cur_spd, temp.last_required_exp, temp.current_exp,
temp.next_required_exp);
if(this_player.players_monster_roster.Count < 6)
{
this_player.players_monster_roster.Add(data_holder_monster);
}
else
{
this_player.players_monster_inventory.Add(data_holder_monster);
}
this_monster.is_captured = false;
this_monster.SetDead();
audio.PlayOneShot(capture_success);
yield return new WaitForSeconds(capture_success.length);
}
else
{
animation["Open_Top"].speed = 5;
animation.Play("Open_Top");
audio.PlayOneShot(capture_fail);
yield return new WaitForSeconds(animation["Open_Top"].length);
col.gameObject.SetActive(true);
col.gameObject.GetComponent<Animation>().enabled = true;
animation["Close_Top"].speed = -5f;
animation["Close_Top"].time = animation["Close_Top"].length;
animation.Play("Close_Top");
yield return new WaitForSeconds(capture_fail.length);
}
Destroy(gameObject);
yield return null;
}
}
据我了解,当你调用协程时,它会等待答案。但是你打电话给他们之后的部分会继续。所以它不会等待那个。答案只会在稍后给出。所以你只需要给你的第一个协程一个值,然后在你唤醒你的刚体之前检查这个值是否存在。
解决了...
Vector3 move_to = new Vector3(transform.position.x-1.5f, col.contacts[0].point.y+1.5f, transform.position.z-1.5f);
while(Vector3.Distance(transform.position, move_to) > 0.01f)
{
rigidbody.velocity = Vector3.zero;
rigidbody.angularVelocity = Vector3.zero;
rigidbody.Sleep();
transform.LookAt(col.transform.position);
transform.position = Vector3.Lerp(transform.position, move_to, 5f * Time.deltaTime);
yield return null;
}
这个 while 循环导致刚体在每次循环时醒来并进入睡眠状态。在最后一次迭代中,刚体仍然处于清醒状态,这导致球在应有的情况下掉落。将其更改为...
rigidbody.velocity = Vector3.zero;
rigidbody.angularVelocity = Vector3.zero;
rigidbody.Sleep();
Vector3 move_to = new Vector3(transform.position.x-1.5f, col.contacts[0].point.y+1.5f, transform.position.z-1.5f);
while(Vector3.Distance(transform.position, move_to) > 0.01f)
{
transform.LookAt(col.transform.position);
transform.position = Vector3.Lerp(transform.position, move_to, 5f * Time.deltaTime);
yield return null;
}
...而且它完美无缺。
我想不通为什么这个协程不会让步。
这段代码...
while(angle > 1.0f)
{
my_transform.rotation = Quaternion.Slerp(my_transform.rotation, fwdRotation, Time.deltaTime * 2.0f);
angle = Quaternion.Angle(my_transform.rotation, fwdRotation);
Debug.Log ("Inside loop" + angle);
yield return null;
}
...不会屈服。它只是通过它。我知道它确实如此,因为在 运行 时间里,我一帧一帧地玩游戏,我可以看到这行代码...
yield return StartCoroutine(MoveBall(col));
rigidbody.WakeUp(); <<<<<<-------THIS ONE RIGHT HERE
...旋转调整完成前执行。为什么会发生这种情况?
using UnityEngine;
using System.Collections;
public class EmptyBall : MonoBehaviour
{
public Ball.BallTypes this_ball_type;
public PlayerCharacter this_player;
public AudioClip capture_attempt;
public AudioClip attempting_capture;
public AudioClip capture_success;
public AudioClip capture_fail;
public GameObject capture_orb_prefab;
private Transform my_transform;
private RaycastHit hit;
private float distance_to_ground;
private CalculateCapture calculate_capture_script = new CalculateCapture();
void Start()
{
my_transform = transform;
}
void Update()
{
if(Physics.Raycast(transform.position, -Vector3.up, out hit)){
distance_to_ground = hit.distance;
}
}
void OnCollisionEnter(Collision col)
{
if(col.gameObject.tag == "Capturable")
{
Monster this_monster = col.gameObject.GetComponent<Monster>();
if(!this_monster.is_captured)
{
audio.PlayOneShot(capture_attempt);
col.gameObject.GetComponent<Animation>().enabled = false;
StartCoroutine(Capture(col));
}
else
{
}
}
else
{
Destroy(this.gameObject);
}
}
private IEnumerator Capture(Collision col)
{
yield return StartCoroutine(MoveBall(col));
rigidbody.WakeUp();
while(distance_to_ground > 0.2f)
{
yield return null;
}
rigidbody.isKinematic = true;
yield return StartCoroutine(TryToCatch(col));
}
private IEnumerator MoveBall(Collision col)
{
Vector3 move_to = new Vector3(transform.position.x-1.5f, col.contacts[0].point.y+1.5f, transform.position.z-1.5f);
while(Vector3.Distance(transform.position, move_to) > 0.01f)
{
rigidbody.velocity = Vector3.zero;
rigidbody.angularVelocity = Vector3.zero;
rigidbody.Sleep();
transform.LookAt(col.transform.position);
transform.position = Vector3.Lerp(transform.position, move_to, 5f * Time.deltaTime);
yield return null;
}
animation["Open_Top"].speed = 5;
animation.Play("Open_Top");
GameObject orb = Instantiate(capture_orb_prefab, col.gameObject.GetComponentInChildren<Renderer>().renderer.bounds.center, Quaternion.identity) as GameObject;
col.gameObject.SetActive(false);
while(Vector3.Distance(my_transform.position, orb.transform.position) > 0.01f)
{
Vector3 orb_target = new Vector3(my_transform.position.x, my_transform.position.y, my_transform.position.z);
orb.transform.position = Vector3.Lerp(orb.transform.position, orb_target, 2.7f * Time.deltaTime);
yield return null;
}
orb.transform.parent = my_transform;
animation["Close_Top"].speed = -5f;
animation["Close_Top"].time = animation["Close_Top"].length;
animation.Play("Close_Top");
Vector3 flatFwd = new Vector3(my_transform.forward.x, 0, my_transform.forward.z);
Quaternion fwdRotation = Quaternion.LookRotation(flatFwd, Vector3.up);
float angle = Quaternion.Angle(my_transform.rotation, fwdRotation);
Debug.Log (angle);
while(angle > 1.0f)
{
my_transform.rotation = Quaternion.Slerp(my_transform.rotation, fwdRotation, Time.deltaTime * 2.0f);
angle = Quaternion.Angle(my_transform.rotation, fwdRotation);
Debug.Log ("Inside loop" + angle);
yield return null;
}
Destroy(orb);
yield return null;
}
private IEnumerator TryToCatch(Collision col)
{
Monster this_monster = col.gameObject.GetComponent<Monster>();
audio.PlayOneShot(attempting_capture);
yield return new WaitForSeconds(attempting_capture.length+1);
bool try_to_capture = calculate_capture_script.AttemptCapture(this_monster.status_condition, this_ball_type, this_monster.cur_hp,
this_monster.cur_max_hp, this_monster.capture_rate);
if(try_to_capture){
this_monster.is_captured = true;
this_monster.trainers_name = this_player.players_name;
Monster temp = this_monster;
PlayerMonsterData data_holder_monster = new PlayerMonsterData (temp.is_setup, temp.is_captured, temp.trainers_name, temp.monster_name,
temp.nick_name,
temp.is_from_trade, temp.level, temp.gender, temp.nature, temp.max_hp,
temp.cur_max_hp, temp.max_atk, temp.max_def, temp.max_spatk, temp.max_spdef,
temp.max_spd, temp.cur_hp, temp.cur_atk, temp.cur_def, temp.cur_spatk,
temp.cur_spdef, temp.cur_spd, temp.last_required_exp, temp.current_exp,
temp.next_required_exp);
if(this_player.players_monster_roster.Count < 6)
{
this_player.players_monster_roster.Add(data_holder_monster);
}
else
{
this_player.players_monster_inventory.Add(data_holder_monster);
}
this_monster.is_captured = false;
this_monster.SetDead();
audio.PlayOneShot(capture_success);
yield return new WaitForSeconds(capture_success.length);
}
else
{
animation["Open_Top"].speed = 5;
animation.Play("Open_Top");
audio.PlayOneShot(capture_fail);
yield return new WaitForSeconds(animation["Open_Top"].length);
col.gameObject.SetActive(true);
col.gameObject.GetComponent<Animation>().enabled = true;
animation["Close_Top"].speed = -5f;
animation["Close_Top"].time = animation["Close_Top"].length;
animation.Play("Close_Top");
yield return new WaitForSeconds(capture_fail.length);
}
Destroy(gameObject);
yield return null;
}
}
据我了解,当你调用协程时,它会等待答案。但是你打电话给他们之后的部分会继续。所以它不会等待那个。答案只会在稍后给出。所以你只需要给你的第一个协程一个值,然后在你唤醒你的刚体之前检查这个值是否存在。
解决了...
Vector3 move_to = new Vector3(transform.position.x-1.5f, col.contacts[0].point.y+1.5f, transform.position.z-1.5f);
while(Vector3.Distance(transform.position, move_to) > 0.01f)
{
rigidbody.velocity = Vector3.zero;
rigidbody.angularVelocity = Vector3.zero;
rigidbody.Sleep();
transform.LookAt(col.transform.position);
transform.position = Vector3.Lerp(transform.position, move_to, 5f * Time.deltaTime);
yield return null;
}
这个 while 循环导致刚体在每次循环时醒来并进入睡眠状态。在最后一次迭代中,刚体仍然处于清醒状态,这导致球在应有的情况下掉落。将其更改为...
rigidbody.velocity = Vector3.zero;
rigidbody.angularVelocity = Vector3.zero;
rigidbody.Sleep();
Vector3 move_to = new Vector3(transform.position.x-1.5f, col.contacts[0].point.y+1.5f, transform.position.z-1.5f);
while(Vector3.Distance(transform.position, move_to) > 0.01f)
{
transform.LookAt(col.transform.position);
transform.position = Vector3.Lerp(transform.position, move_to, 5f * Time.deltaTime);
yield return null;
}
...而且它完美无缺。