【问题标题】:How to stop rotation in clones?如何停止克隆中的旋转?
【发布时间】:2019-07-21 12:57:41
【问题描述】:

我有一些预制件。每个对象都有一个允许其旋转的脚本(脚本“Rotation”)。每次按下添加到 Unity 场景主屏幕中的按钮时,我都会尝试停止克隆对象的旋转速度几秒钟。认为最好的解决方案是找到具有特定标签的每个对象(所有克隆都具有相同的标签)。按下按钮后,每个带有指定标签的对象都应该停止。不幸的是,它不适用于克隆对象...谁能解决我的问题?

每个克隆都有一个轮换脚本:

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

public class Rotation : MonoBehaviour {

    public float speed;
    public float speed2 = 0f;
    private Rigidbody2D rb2D;


    // Use this for initialization
    void Start () {

    }

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

        transform.Rotate (0, 0, speed);
    }

    public void Stop (){

        StartCoroutine(SpeedZero());
        Debug.Log ("ZEROOOOO");
    }

    IEnumerator SpeedZero()
    {
        transform.Rotate (0, 0, speed2);
        yield return new WaitForSeconds(20);
        transform.Rotate (0, 0, speed);

    }
}

使用 SunSpawner 脚本生成对象:

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

public class SunSpawner : MonoBehaviour {


    public GameObject[] theSuns;
    public Transform generationPoint;


    private int sunSelector;
    private float sceneHeight;

    float distance = 0.5f;


    Vector3 maxWidthPoint;
    Vector3 minWidthPoint;

    //Radious base on circle collider radious
    float lastSunRadious = 2f;

    public void Update (){

        if (transform.position.y < generationPoint.position.y) {

            sunSelector = Random.Range(0, theSuns.Length);
            float currentSunRadious = theSuns[sunSelector].GetComponentInChildren<CircleCollider2D>().radius * theSuns[sunSelector].GetComponentInChildren<CircleCollider2D>().transform.localScale.x * theSuns[sunSelector].transform.localScale.x;
            float distanceBetween = distance + lastSunRadious + currentSunRadious; //Random.Range(lastSunRadious+currentSunRadious, sceneHeight);
            float sunXPos = Random.Range(minWidthPoint.x + currentSunRadious, maxWidthPoint.x - currentSunRadious);

            Vector3 newSunPosition = new Vector3(sunXPos, transform.position.y + distanceBetween, transform.position.z);

            transform.position = newSunPosition;
            lastSunRadious = currentSunRadious;
            Instantiate (theSuns [sunSelector], transform.position, transform.rotation);

        }
    }
}

现在我添加了 Canvas 和一个按钮,我想在其中使用 OnClick 函数来停止每个存在并具有特定标签(在我的例子中是“日志”)的对象(克隆)中的旋转。正如我所写,我做不到。我尝试了一些东西,创建一个列表,搜索一个标签,参考 Rotation 脚本并运行协程,但没有任何效果。目前,我没有为停止按钮添加任何脚本,因为我不知道如何解决它。

【问题讨论】:

    标签: c# unity3d rotation 2d


    【解决方案1】:

    一种方法是通过事件。
    旋转对象在它们被实例化的那一刻订阅一个事件,并且您使用您的按钮来调用该事件,从而有效地改变它们的状态。


    在 Canvas 上的组件下:
    (它不必直接在 Canvas 游戏对象下,而是在代码中的任何位置。重要的是调用方法)

    // Call these methods from your onClick from the appropriate button.
    // For example the Stop button should call StopClonesRotation().
    public void StopClonesRotation() { Rotation.StopRotating(); }
    public void StartClonesRotation() { Rotation.StartRotating(); }
    

    旋转脚本
    (这个脚本应该在你场景中的每个旋转对象上)
    (上面的脚本调用这个类的静态方法)

    public delegate void RotateAction();
    public static event RotateAction StopRotating;
    public static event RotateAction StartRotating;
    
    RotateAction startAction;
    RotateAction endAction;
    
    public float Speed;
    bool shouldRotate = true;
    
    
    private void Awake() {
        startAction = () => shouldRotate = true;
        endAction = () => shouldRotate = false;
    }
    void OnEnable() {
        StartRotating += startAction;
        StopRotating += endAction;
    }
    void OnDisable() {
        StartRotating -= startAction;
        StopRotating -= endAction;
    }
    
    void Update () {
       if (!shouldRotate) { return; }
       transform.Rotate (0, 0, Speed);
    }
    

    另一种方法是FindObjectsOfType(),它的性能远低于事件。
    (文档链接:https://docs.unity3d.com/ScriptReference/Object.FindObjectsOfType.html

    在画布上的组件下:

    // Call these methods from your onClick from the appropriate button.
    // For example the Stop button should call StopClonesRotation().
    public void StopClonesRotation() { 
       var allRotatingObjects = FindObjectsOfType<Rotation>();
       foreach (var rotatingObj in allRotatingObjects) { rotatingObj.shouldRotate = false; }
    }
    public void StartClonesRotation() { 
       var allRotatingObjects = FindObjectsOfType<Rotation>();
       foreach (var rotatingObj in allRotatingObjects) { rotatingObj.shouldRotate = true; }
    }
    

    旋转脚本
    (此脚本应位于场景中的每个旋转对象上)

    public float Speed;
    bool shouldRotate = true;
    
    void Update () {
       if (!shouldRotate) { return; }
       transform.Rotate (0, 0, Speed);
    }
    

    【讨论】:

    • 谢谢。不确定它是否适用于直接取消订阅的 lamdas,但确定有人会发现这一点 :) 编辑了使用缓存操作的答案。
    • 我在阅读您的答案几分钟后遇到了一个 lambda 事件问题,否则我不会注意到。 :P 理智上我知道 lambda 问题,我只是没有注意到。
    猜你喜欢
    • 2022-08-09
    • 2012-05-31
    • 1970-01-01
    • 2015-06-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-24
    相关资源
    最近更新 更多