2016-11-30 10 views
4

그래서 나는 두 개의 볼을 충돌시키고, 스스로 파괴하고, 그 자리에 또 다른 볼을 스폰하기를 원한다. 그러나 스크립트를 볼에 붙이려고 할 때 볼의 두 인스턴스가 모두 접촉했을 때 파괴되고 두 볼의 프리 패브가 즉시 생성됩니다. 왜냐하면 두 인스턴스 모두 코드를 가지고 있기 때문입니다. 이로 인해 두 볼은 서로 스폰하고 서로를 계속 파괴합니다.Unity - 같은 GameObject 두 개를 충돌시키고 서로 파괴하고 목표 위치에 새 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; 
} 

방법, 다음 조립식의 하나 개의 인스턴스를 생성이 코드는 모두 공을 파괴해야합니까 : 나는 공에 부착이 스크립트가?

+0

이것은 유니티/게임 프로그래밍의 절대적인 기초입니다. 당신은 단순히 "다른 하나를 파괴하십시오."그것은 "그 하나를 파괴"하는 것을 멈추게 할 것입니다. Unity에서는 물리 루프를 파괴 할 수 없기 때문에 단순히 부울을 설정합니다. 다른 시스템에서는 파괴하거나, 스크립트를 사용하지 않거나, 단지 부울을 설정합니다. Kardux는 올바른 기본 대답을주었습니다. – Fattie

+0

Yoj가 발생시키는 또 다른 문제는 일반적으로 Unity에서 "태그"를 사용하지 않는다는 것입니다. 정말로이 단계에서는 ** 물리 ** 레이어 ** 시스템을 사용해야합니다. 당신은 그것 없이는 결코 사소한 Unity 프로젝트를 할 수 없습니다. (유니티 (Unity)와 같은 몇 가지 상황이 있습니다 : Unity에서 첫 2 일간 새로운 학습자를 얻는 "안녕하세요 세상"시스템을 만들려고 노력하지만 실제로 도움이되지 않습니다. 레이어 개념, 처음부터 그것을 사용할 수도 있습니다.) – Fattie

+0

@JoeBlow, 지금까지 이것이 제 첫 번째 프로젝트 였고, 자습서를 따랐을 때 태그를 사용하여이 작업을 배웠습니다.이 작업은 얼마나 간단한 프로젝트입니까? . 레이어를 다루는 훌륭한 자습서를 추천 해 주시겠습니까? – YojaX

답변

1

또한 첫 번째 볼에만 설정되는 부울을 스크립트에 사용할 수 있습니다

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() 메소드 호출은 새 공을 산란한다

완전히 일반적인 스크립트 또는 패턴 난의
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); 
     } 

    } 

n 통합.

그래서 개념적으로 "다른 하나를 파괴하십시오"; 스크립트 중 하나가 먼저 실행되어야하므로 정상적으로 작동합니다. Unity의 다른 시스템에서는 다음 중 하나를 할 수 있습니다 :

  • A는 어떤 방식 으로든 다른 게임 객체를 "파괴"합니다. Unity에서 DestroyImmediate(col.gameObject)이됩니다.

  • B는 어떤 방식 으로든 다른 스크립트를 "파괴"하거나 비활성화합니다. Unity에서 col.gameObject.GetComponent<TwoToOne>().enabled = false이 될 것입니다.

  • C, 여기에 표시된 것처럼 다른 게임 개체에 "플래그"(부울 값 설정)가 있습니다.

공교롭게도 화합, 특히 당신은 A 또는 B를 할 수 없어, 이제 C을위한, 그래서 당신은 단지 C. B는 가장 우아한 솔루션입니다, 그러나 그것은 Unity5에서 작동하지 않습니다 !

+1

HI Kardux, 방금 "Two to One"스크립트를 추가했습니다. 그것은 평범한 일입니다. (FWIW는 어쨌든 물리학에서 레이어를 사용해야합니다.) – Fattie

+1

@JoeBlow 추가 한 내용이 더 간단하다는 데 동의하지만 @YojaX는 충돌하는 볼을 모두 파괴하고 새 인스턴스를 만들고 싶다고 말했습니다. 게다가 그가 지금까지 만든 정신을 지키고 싶었습니다. :) 그래, 나도 네 방식대로 할거야. 인스턴스화를 피하고 새 공으로 두 개의 기존 공 중 하나를 사용하는 것이 훨씬 낫다. 돌아 오기 전에'doNothing'을'false'로 설정하면 다가오는 충돌과 함께 작동합니다.) – Kardux

+1

HI @Kardux. 네, 꼭 대답해야합니다. (새로운 답변을 만드는 것보다 좋은 답변에 더 많은 정보를 추가하는 것이이 사이트에서 일반적입니다.) 멋진 하루 되세요. – Fattie

-2

당신이 할 수있는 일은 볼을 파괴 만하고 스폰하지 않고 다른 볼을 두 번째 볼에 붙이는 또 다른 스크립트를 만드는 것입니다. 첫 번째 공은 파괴와 재 생 기능을 모두 갖습니다. 두 볼이 서로 파괴 할 때 하나는 부활하고 다른 하나는 두 번째 볼에 스폰 기능을 연결하지 않았기 때문에 발생하지 않습니다.

0

delegates 또는 @JoeBlow가 권장하는대로 이벤트 관리자에서 UnityEvents을 사용하여이를 해결할 수 있습니다.

다음 예제에서는 대리인을 사용하도록 선택했습니다.

두 개의 스크립트가 있습니다. 하나는 이미 가지고있는 구체에 있고 다른 하나는 인스턴스화하지 않고 응용 프로그램의 다른 스크립트에서 참조 할 수있는 정적 클래스입니다.


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; 
    } 
} 

가 왜이 방법을 사용합니까?

이 방법은 단일 위치에서 여러 개의 '사건'이 발생하는 것을 제어하는 ​​데 이상적입니다. 이 경우, 우리는 충돌하는 각 볼에 대해 각 볼에 기능을 트리거합니다. 그런 다음 EventManager는 하나의 큐브를 생성하고 그 다음에이 큐브를 생성하고 나머지 큐브에 충돌이 장면의 다른 위치에서 발생했음을 알립니다.

+1

안녕 Zzzzze! 두 가지 문제가 있습니다 : (1) "다른 하나를 먼저 파괴하십시오"스크립트는 게임에서 절대적으로 표준입니다. 흥미로운 점은 흥미롭게도 마지막 파라에서 묘사 한 문제가 존재하지 않는다는 것입니다. 논리적으로 그들은 모두 "지워진다."(3) Unit :; 당신이 링크 한 통합 튜토리얼은 Unity 문서의 가장 나쁜 부분 중 하나입니다 (*** 그리고 그것은 뭔가를 말하고 있습니다 !! ***) 또한 방법, 길, 구식입니다, (4) UnityEvent를 요즘 사용해야합니다 http://stackoverflow.com/a/36249404/294884 – Fattie

+0

안녕하세요. @JoeBlow .. 내 활동 피드를보고 나를 따라 다니십니까? 하하 - 귀하의 의견을 수용하기 위해 제 답변을 업데이트했습니다. UnityEvents를 사용하기 위해 예제를 아직 변경하지 않았지만, 시간이있을 때 이것을 할 것입니다. 내가 당신의 관심을 가지고있는 동안, 또 다른 질문에 대한 나의 대답에 대해서도 의견을 말씀해 주시겠습니까 - 시간이 있다면 ... 당신의 생각을 듣고 싶습니다 - http://stackoverflow.com/questions/40564137/weird-lines-3d- 화합/40599689 # 40599689 건배! – Zze