2016-11-30 9 views
4

私は2つのボールを衝突させて破壊し、別のボールをその場所に(好ましくは特定の速度で)発動させたいと考えています。しかし、私がボールにスクリプトを添付しようとすると、ボールの両方のインスタンスが接触すると破棄され、すぐにボールの2つのプレハブが生成されます。これにより、両方のボールが互いに出現し、互いに破壊することが繰り返されます。私はボールにこのスクリプトを添付しました:Unity - 同じGameObjectのうちの2つを衝突させ、お互いを破壊し、目標位置に新しいGameObjectをスポーンする方法?

private Vector3 ballPosition; 

void OnTriggerEnter2D (Collider2D other) { 

    if (other.gameObject.tag == "Ball") { 

     ballPosition = new Vector3 ((transform.position.x + other.transform.position.x)/2, (transform.position.y + other.transform.position.y)/2, 0.0f); 
     StartCoroutine ("RespawnBall"); 
    } 
} 

IEnumerator RespawnBall() { 

    Instantiate (gameObject, ballPosition, Quaternion.identity); 
    Destroy (gameObject); 
    yield return null; 
} 

は、どのように私は、このコードは、両方のボールを破壊作るのですか、その後、プレハブのインスタンスを1つだけ出現しますか?

+0

これは、Unity /ゲームプログラミングの絶対的な基本です。あなたは単に「他のものを破壊する」ことができます。それはそれを「破壊する」ことを止めるでしょう。 Unityでは、物理ループ内で破壊することはできないので、ブール値を設定するだけです。異なるシステムでは、破壊するか、スクリプトを無効にするか、またはブール値を設定するだけです。 Karduxは正しい基本的な答えを出しました。 – Fattie

+0

Yojが引き起こす別の問題は、一般的にUnityで「タグ」のものを使用しないということです。本当にこの段階では、物理学のために**レイヤー**システムを利用する必要があります。あなたはそれがないと、自明なUnityプロジェクトを行うことはできません。 (Unityのようないくつかの状況があります:彼らはユニティで最初のカップルの日に新しい学習者を獲得する "hello world"システムを作りようとしますが、それは本当に助けになりません。レイヤーコンセプト、最初からそれを使用することもできます) – Fattie

+0

@JoeBlow、これまでのところ私の最初のプロジェクトです。チュートリアルの後で、タグを使ってこれを行う方法を学びました。 。レイヤーを扱う良いチュートリアルをお勧めしますか? – YojaX

答えて

1

スクリプトでブール値を使用することもできます完全に共通スクリプトやパターンIです

public class TwoToOne : MonoBehaviour { 

    public bool doNothing; 

    void OnCollisionEnter (Collision col) 
     { 
     if (doNothing) return; 

     col.gameObject.GetComponent<TwoToOne>().doNothing = true; 
     Destroy(col.gameObject); 

     GameObject newCube = Instantiate(gameObject); 

     Destroy(gameObject); 
     } 

    } 

:ちょうどこれを行う、単に

private Vector3 ballPosition; 
public bool spawnNewBall; 

void Start() { 
    spawnNewBall = true; 
} 

void OnTriggerEnter2D (Collider2D other) { 

    if (other.gameObject.tag == "Ball") { 

     if (spawnNewBall) { 
      other.GetComponent</*YourScriptName*/>().spawnNewBall = false; 
     } 

     ballPosition = new Vector3 ((transform.position.x + other.transform.position.x)/2, (transform.position.y + other.transform.position.y)/2, 0.0f); 
     StartCoroutine ("RespawnBall"); 
    } 
} 

IEnumerator RespawnBall() { 
    if (spawnNewBall) { 
     Instantiate (gameObject, ballPosition, Quaternion.identity); 
    } 
    Destroy (gameObject); 
    yield return null; 
} 

より:そのOnTriggerEnter2D()メソッド呼び出しは、新しいボールを起動しますn統一。

概念的には、「もう一方を破壊する」ことです。スクリプトの1つが最初に実行されなければならないので、正常に動作します。 Unityから別のシステムでは、これらのもののいずれかを行うことができます

  • A、何らかの方法で他のゲームオブジェクトを「破壊します」。それはUnityのDestroyImmediate(col.gameObject)でしょう。

  • Bは、何らかの方法で他のスクリプトを "破棄"するか無効にします。ユニティでcol.gameObject.GetComponent<TwoToOne>().enabled = falseとなるでしょう

  • C、ここに示すように、他のゲームオブジェクトの "フラグ"(ブール値を設定します)。

偶然にも、ユニティに特異的に、あなたはAまたはBを行うことはできませんので、今Cを行うためので、あなただけのC. Bが最もエレガントなソリューションですけど、それはUnity5では動作しません。 !

+1

HI Kardux、私は典型的な "Two To One"スクリプトを追加しました。それは普通のことです。とにかく物理学のレイヤーを使用していなければなりません。 – Fattie

+1

@JoeBlowあなたが追加したものがよりシンプルであることに同意しますが、@ YojaXは衝突するボールを破壊して新しいボールをインスタンス化したいと述べました。私はそれをあなたのやり方もやっています:インスタンス化を避け、単に新しい2つのボールのうちの1つを使っている方がはるかに優れています(私は単純にリセットします戻ってくる前に 'doNothing'を' false'にして、次の衝突でうまくいくようにしてください) – Kardux

+1

HI @Kardux。はい、是非、あなたの答えは正しいものです。 (このサイトでは、新しい回答を作成するのではなく、良い答えに多くの情報を追加するのが一般的です。)素晴らしい一日です。 – Fattie

-2

あなたができることは、ボールを破壊するだけですがスポーンして2番目のボールにアタッチしない別のスクリプトを作成することです。最初のボールには破壊と再創造の両方の機能があります。あなたが2番目のボールにスポーンフィーチャを付けなかったので、2つのボールがお互いを破壊すると、1つは再生成され、もう1つは表示されません。

0

delegatesを使用して解決できます。また、@JoeBlowが推奨するように、イベントマネージャーからUnityEventsを使用しても解決できます。

次の例では、代理人を使用することを選択しました。

2つのスクリプトがあります。 (既に持っている)球面上にあるものと、インスタンス化せずにアプリケーションの他のスクリプトから参照できる静的なクラスです。


EventManager。CS

using UnityEngine; 
using System.Collections; 

public static class EventManager{ 

    // Create our delegate with expected params. 
    // NOTE params must match SphereScript.PostCollision declaration 
    public delegate void CollideEvent(string message); 

    // Create the delegate instance. This is the one we will invoke. 
    public static event CollideEvent PostCollision; 

    // Called whenever an object has collided with another 
    public static void Collision(GameObject obj1, GameObject obj2, Vector3 collisionPoint){ 
     if (obj1.GetComponent<sphereScript>().isAlive && obj2.GetComponent<sphereScript>().isAlive) { 

      //Kill the 2 objects which haev collided. 
      obj1.GetComponent<sphereScript>().Kill(); 
      obj2.GetComponent<sphereScript>().Kill(); 

      //Create a cube. 
      GameObject cube = GameObject.CreatePrimitive (PrimitiveType.Cube); 
      cube.transform.position = collisionPoint; 

      // Invoke delegate invocation list 
      PostCollision("Something is dead"); 
     } 
    } 
} 

SphereScriptは.cs

using UnityEngine; 
using System.Collections; 

public class sphereScript : MonoBehaviour { 
    // Am I alive? 
    public bool isAlive; 

    // Use this for initialization 
    void Start() { 
     // Add a function we want to be called when the EventManager invokes PostCollision 
     EventManager.PostCollision += PostCollision; 
     isAlive = true; 
    } 

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

    } 

    //Invoked from EventManager.PostCollision delegate 
    void PostCollision(string message){ 
     if(isAlive) 
      Debug.Log (this.name + " message received: " + message); 
    } 

    // Called when it is time to destroy this gameobject 
    public void Kill(){ 
     isAlive = false; 
     Destroy (this.gameObject); 
    } 

    //On collision with another object 
    void OnCollisionEnter2D(Collision2D collision){ 
     if (collision.gameObject.GetComponent<sphereScript>()) { 
      EventManager.Collision (this.gameObject, collision.gameObject, collision.contacts [0].point); 
     } 
    } 

    // Called after this object has been destroyed 
    void OnDestroy(){ 
     // cleanup events for performance. 
     EventManager.PostCollision -= PostCollision; 
    } 
} 

、なぜこの方法を使用できますか?

この方法は、1つの場所から複数の「出来事」のリリースを制御するのに理想的です。この場合、衝突するボールのそれぞれのボールに関数をトリガーします。その後、EventManagerは1つのキューブをウェイクアップして作成し、それに続いて残りのキューブにシーンのどこかで衝突が発生したことを通知します。

+1

ちょっとZzzzze!興味深いことに、あなたが最後のパラで説明した問題は存在しません:(1)「他のものを最初に破壊する」というスクリプトは、ゲームでは絶対に標準です。論理的には、それらはすべて「消去」されます。(3)ユニット内では、ある程度、「そのような代表者を使用しないでください」。あなたがリンクした統一チュートリアルは、Unityドキュメンテーションの最悪のものの1つであることはよく知られています(***そしてそれは何かを言っています!! ***)また、方法、方法、方法の古さです、(4) http://stackoverflow.com/a/36249404/294884 – Fattie

+0

こんにちは@JoeBlow ..あなたは私の活動フィードを見て、私の周りをフォローしていますか?ハハ - 私はあなたのコメントに対応するために私の答えを更新しました。私はまだUnityEventsを使用するために例を変更するのですが、私は時間があるときにこれを行います。私はあなたの注意を払っている間、別の質問のために私の答えにコメントしてもらえますか?あなたは時間があれば...あなたの考えを聞きたいですか?http://stackoverflow.com/questions/40564137/weird-lines-3d-団結/ 40599689#40599689乾杯! – Zze

関連する問題