Unity 3 Dを使用するには詳細に注意する必要があります

15090 ワード

操作localPositionの場合はご注意ください
GameObjectを移動するのはごく普通のことで、コードを見ると簡単に見えます.
transform.localPosition += new Vector3 ( 10.0f * Time.deltaTime, 0.0f, 0.0f );      ,      GameObject   parent,     parent GameObject localScale (2.0f,2.0f,2.0f)。  GameObject    20.0   / 。    GameObject world position  : 
Vector3 offset = new Vector3( my.localPosition.x * parent.lossyScale.x,
                              my.localPosition.y * parent.lossyScale.y,
                              my.localPosition.z * parent.lossyScale.z );
Vector3 worldPosition = parent.position + parent.rotation * offset;     ,        localPosition         scale        ,        ,Unity3D   Translate  ,          : 
transform.Translate ( 10.0f * Time.deltaTime, 0.0f, 0.0f ); 

Inspectorに曝された変数も同様にAnimation ViewEditorで使用できる
Unity 3 Dに付属のAnimation View Editorを使って簡単なアニメーション操作をしたい場合があります.Animation Editorでは、Unity 3 D自体のcomponentだけでなく、カスタマイズしたMonoBehaviorの各Propertyも操作できます.float値を追加するには曲線で操作する必要があります.簡単にserialize可能なタイプに暴露することができます.例えば、次のようにします.
public float foobar = 1.0f;

これにより、この変数はInspectorだけでなく、animation viewで操作して、AnimationClipを生成して、AnimationComponentで呼び出すことができます.
例:
public class TestCurve : MonoBehaviour {
    public float foobar = 0.0f;
 
    IEnumerator Start () {
        yield return new WaitForSeconds (2.0f);
        animation.Play("foobar_op");
        InvokeRepeating ( "LogFoobar", 0.0f, 0.2f );
        yield return new WaitForSeconds (animation["foobar_op"].length);
        CancelInvoke ("LogFoobar");
    }
 
    void LogFoobar () {
        Debug.Log("foobar = " + foobar);
    }
} 

 
GetComppnent親タイプを取得できます
Unity 3 DではMonoBehaviorを派生させることができますので、次のコードがあります.
public class foo : MonoBehaviour {
    ...
}
 
public class bar : foo {
    ...
}

仮に私たちが今A,Bの2つのGameObjectを持っていて、Aはfooを含んで、Bはbarを含んで、私たちが書く時
foo comp1 = A.GetComponent<foo>();
bar comp2 = B.GetComponent<bar>();

comp 1が見え、comp 2はすべて必要なComponentを手に入れた.Bの操作を次のように変更します.
foo comp2 = B.GetComponent<foo>();

答えはcomp 2かbar Componentを返しfooタイプに変換します.同様に、有効な変数を下に変換することができます.
bar comp2_bar = comp2 as bar;

GetComponent()は,Componentを設計する際に結合性をより低くすることができる.
Invoke、yieldなどの関数はTimeを受けます.timeScaleの影響
Unity 3 Dは時間を調整するのに非常に便利な関数Timeを提供した.timeScale.Unity 3 Dを初めて使用する利用者に対してはTimeと誤導的に考える.timeScaleは、ゲーム中の一時停止(Pause)と開始(Resume)にも適用できます.多くの人が書き慣れています
Time.timeScale = 0.0f

ゲームの一時停止/開始は、ゲームシステムの設計の一部であり、Time.timeScaleはこの部分の操作ではありません.正しい方法は、一時停止する必要があるスクリプトまたはGameObjectを収集し、enabled=falseを設定することでスクリプトアクティビティを停止するか、特定の関数を使用してこれらのオブジェクトを一時停止する場合にそれらの操作を閉じる必要があります.
Time.timeScaleはゲーム中のスローレンズの再生などの操作が多く,サーバ側主導のゲームではこのような操作を避けるべきである.特筆すべきは、Unity 3 Dの多くの時間依存関数がtimeScaleに関連付けられているのに対し、timeScale=0.0 fはこれらの関数またはアニメーションを完全に停止させ、これもなぜ一時停止操作に適していないのかの主な原因である.
ここでは、timeScaleの影響を受ける主な関数とComponentをいくつか示します.
MonoBehaviour.Invoke(…)

MonoBehaviour.InvokeRepeating(…)

yield WaitForSeconds(…)

GameObject.Destroy(…)

Animation Component

Time.time, Time.deltaTime



CoroutineとIEnumeratorの関係
Unity 3 D C#スクリプトを初めて書くとき、Coroutine関数を呼び出してStartCoroutineの使い方を忘れてしまうというエラーがよくあります.次のようになります.
TestCoroutine.cs
IEnumerator CoLog () {
    yield return new WaitForSeconds (2.0f);
    Debug.Log("hello foobar");
}

上記の関数を次のコードで呼び出すと、
TestCoroutine  testCo = GetComponent<TestCoroutine>();
testCo.CoLog ();
testCo.StartCoroutine ( "CoLog" );

ではtestCo.CoLog()の呼び出しは何の役にも立たない.
StartCoroutine,InvokeRepeatingとその呼び出し元の関連付け
通常、GameObjectでStartCoroutineまたはInvokeRepeatingを呼び出すには、次のように書きます.
StartCoroutine ( Foobar() );
InvokeRepeating ( "Foobar", 0.0f, 0.1f );

このGameObjectがdisableまたはdestroyになった場合、coroutineおよびinvokesはキャンセルされます.手動で呼び出すのと同じです
StopAllCoroutines ();
CancelInvoke ();

これは美しく見えますが、AIにとって、NPCが死んだことを教えているように、あなた自身の小さな動作を聞いてみましょう.
しかし、このようなコードが1つのマネージャータイプの制御AIに使われている場合、他のAIを制御する可能性があり、Invoke,Coroutineを通じてマイクロスレッドの操作を行う可能性があり、このときStartCoroutineやInvokeRepeatingの呼び出し者の設計を明確にしなければならないことに注意してください.議論する前に、StartCoroutineまたはInvokeRepeatingの呼び出しは、MonoBehaviorでThread Stateを開き、操作する必要がある関数、変数、およびタイマをこのStackに入れて、エンジンのフレームごとにUpdateの最後に、Renderレンダリングの前に統一的に処理することを理解しておく必要があります.だから、このMonoBehaviorがDestroyになったら、このThread Stateも消えて、彼が保存しているすべての呼び出しも失効します.
2部のGameObject AとBがあれば、彼らは互いに相手を知っていて、もしAの中でStartCoroutineあるいはInvokeRepeatingを通じてBの関数を呼び出してBを制御するならば、この時Thread StateはAの中に保管して、Aがdisableあるいはdestroyになった時、これらのしばらくの時間を必要とする制御関数も失効して、この時Bはまだ死んでいないのに、動かないかもしれません.より良い方法は、Aの関数にB.StartCoroutine(...)を介してこのThread StateをBに格納することです.
// class TestCortouine
public class TestCoroutine : MonoBehaviour {
    public IEnumerator CoLog ( string _name ) {
        Debug.Log(_name + " hello foobar 01");
        yield return new WaitForSeconds (2.0f);
        Debug.Log(_name + " hello foobar 02");
    }
}
 
// component attached on GameObject A
public class A: MonoBehaviour {
    public GameObject B;
 
    void Start () {
        TestCoroutine  compB = B.GetComponent<TestCoroutine>();
 
        // GOOD, thread state in B
        // same as: compB.StartCoroutine ( "CoLog", "B" );
        compB.StartCoroutine ( compB.CoLog("B") );
 
        // BAD, thread state in A
        StartCoroutine ( compB.CoLog("A") );
 
        Debug.Log("Bye bye A, we'll miss you");      
        Destroy(gameObject); // T_T I don't want to die...
    }	
}

上記のコードでは、次の結果が得られます.
B hello foobar 01
A hello foobar 01
Bye bye A, we'll miss you
B hello foobar 02

Start,Update,LateUpdate関数が不要な場合は削除してください
スクリプトにStart,Update,LateUpdate関数がない場合、Unity 3 Dはそれらを彼のUpdateリストに追加せず、スクリプト全体の効率の向上に役立ちます.
この2つのスクリプトの違いを見ることができます.
Update_01.cs
public class Update_01 : MonoBehaviour {
    void Start () {}
    void Update () {}
}

Update_02.cs
public class Update_02 : MonoBehaviour {
}