簡體   English   中英

當語句彼此碰撞時,Unity 2D C#gameObject不會激活其他gameObjects。 為什么?

[英]Unity 2D C# gameObject does not activate other gameObjects if statements when colliding with each other. Why?

該游戲的工作方式是從一個最大的球開始。 當火箭擊中大球時,它分裂成兩個中球,然后分裂成兩個小球。 當火箭擊中最小的球時,它將被摧毀。

我遇到的問題是,當火箭與球相撞時。 火箭被摧毀了,但是球沒有“分成”兩個大球,依此類推。

我只是注意到了這一點,我想知道如果我將此代碼語句轉為==“最小的球”而不是!=,是否可以解決我的問題。

    if (target.tag == "Rocket")
    {
        if (gameObject.tag != "Smallest Ball")
        {
            InstantializeBallsonoff();
        }
        else {
            AudioSource.PlayClipAtPoint(popsounds[Random.Range(0, popsounds.Length)], transform.position);
            //play random audio in the popsounds array at current position of ball
            gameObject.SetActive(false); //deactivate the gameobject
        }
    }
}//ontriggerenter

這是我的球形腳本的完整代碼

using UnityEngine;
using System.Collections;

public class Ball : MonoBehaviour {

private float forceX, forceY;
private Rigidbody2D ball;

[SerializeField]
private bool moveLeft, moveRight;

[SerializeField]
private GameObject originalBall;

private GameObject ball1, ball2;
private Ball ball1script, ball2script;

[SerializeField]
private AudioClip[] popsounds; //array

// Use this for initialization
void Awake () {
    ball = GetComponent<Rigidbody2D>();
    ballspeed();
}

// Update is called once per frame
void Update () {
    ballmovement();
}

void InstantiatingBalls()
{
    if (this.gameObject.tag != "Smallest Ball")
    {
        ball1 = Instantiate(originalBall); //create copy of originalball into ball1
        ball2 = Instantiate(originalBall);

        ball1.name = originalBall.name;
        ball2.name = originalBall.name;

        ball1script = ball1.GetComponent<Ball>(); //get the ball script 
        ball2script = ball2.GetComponent<Ball>();

    }
}//InstantiatingBalls

void InstantializeBallsonoff() {
    InstantiatingBalls();

    Vector3 temp = transform.position; //start from current ball location
    ball1.transform.position = temp;
    ball1script.setmoveLeft(true);
    ball2.transform.position = temp;
    ball2script.setmoveRight(true);

    ball1.GetComponent<Rigidbody2D>().velocity = new Vector2(0, 2.5f); //x,y
    ball2.GetComponent<Rigidbody2D>().velocity = new Vector2(0, 2.5f); //x,y

    AudioSource.PlayClipAtPoint(popsounds[Random.Range(0, popsounds.Length)], transform.position);
    //play random audio in the popsounds array at current position of ball
    gameObject.SetActive(false); //deactivate the gameobject

}//InstantializeBallsonoff

public void setmoveLeft(bool moveLeft) { //canMoveLeft
    this.moveLeft = moveLeft;
    this.moveRight = !moveLeft; //moveRight is now false b/c we set moveLeft to true
}

public void setmoveRight(bool moveRight) {//canMoveRight
    this.moveRight = moveRight;
    this.moveLeft = !moveRight;
}

void ballmovement() {
    if (moveLeft) {
        Vector3 temp = transform.position; //current position of ball
        temp.x -= Time.deltaTime; // represent time per frame
        transform.position = temp;
    }

    if (moveRight) {
        Vector3 temp = transform.position; //current position of ball
        temp.x += Time.deltaTime; // represent time per frame
        transform.position = temp;
    }
}

void ballspeed() {
    forceX = 2.5f;

    switch (this.gameObject.tag) {
        //this refers to gameobject that holds this script

        case "Largest Ball":
            forceY = 11.5f;
            break;
        case "Large Ball":
            forceY = 10.5f;
            break;
        case "Medium Ball":
            forceY = 9f;
            break;
        case "Small Ball":
            forceY = 8f;
            break;
        case "Smallest Ball":
            forceY = 7f;
            break;
    }//switch

}//ballspeed

void OnTriggerEnter2D (Collider2D target) {
    if (target.tag == "Ground") {
        ball.velocity = new Vector2(0, forceY);
    }

    if (target.tag == "Right Wall") {
        setmoveLeft(true);
        /*moveRight = false;
        moveLeft = true;*/
    }

    if (target.tag == "Left Wall")
    {
        setmoveRight(true);
        /*moveRight = true;
        moveLeft = false;*/
    }

    if (target.tag == "Rocket")
    {
        if (gameObject.tag != "Smallest Ball")
        {
            InstantializeBallsonoff();
        }
        else {
            AudioSource.PlayClipAtPoint(popsounds[Random.Range(0, popsounds.Length)], transform.position);
            //play random audio in the popsounds array at current position of ball
            gameObject.SetActive(false); //deactivate the gameobject
        }
    }
}//ontriggerenter


 }//ball

這是我代碼的一部分,當火箭與大球和頂部碰撞時,火箭會被摧毀。 這是我遇到的另一部分。

void OnTriggerEnter2D(Collider2D target) {
    if (target.tag == "Top") {
        Destroy(gameObject);
    }

    string[] ballhit = target.name.Split();
    /*array ballhit
    split = deletes the space between two words and make it so it takes 2 spaces in the array*/

    for (int s = 0; s < ballhit.Length; s++) {
        Debug.Log("The array contains: " +ballhit [s]);

        if (ballhit.Length > 1)
        { //ball names will always be more than 1 length "Largest Ball"
            if (ballhit[1] == "Ball")
            {
                Destroy(gameObject);
            }//destroy object
        }//ballhit name length
    }// name increments

}//triggerCollider

這是我完整的火箭劇本

using UnityEngine;
using System.Collections;

public class Rocket : MonoBehaviour {

private Rigidbody2D rocket;
private float speed = 5f;


// Use this for initialization
void Awake () {
    rocket = GetComponent<Rigidbody2D>();
}

// Update is called once per frame
void Update () {
    rocket.velocity = new Vector2(0, speed); //x, y rocket movement
}

void OnTriggerEnter2D(Collider2D target) {
    if (target.tag == "Top") {
        Destroy(gameObject);
    }

    string[] ballhit = target.name.Split();
    /*array ballhit
    split = deletes the space between two words and make it so it takes 2 spaces in the array*/

    for (int s = 0; s < ballhit.Length; s++) {
        Debug.Log("The array contains: " +ballhit [s]);

        if (ballhit.Length > 1)
        { //ball names will always be more than 1 length "Largest Ball"
            if (ballhit[1] == "Ball")
            {
                Destroy(gameObject);
            }//destroy object
        }//ballhit name length
    }// name increments

}//triggerCollider

}//rocket

您的代碼比需要的要復雜得多,因此很難找到實際的錯誤。

首先,您的moveLeftmoveRight互斥。 您只需要其中之一。 我想用public int currentDirection替換這兩者,您將right設置為1,將left設置為-1。
您的新ballMovement方法可以簡單地是:

void MoveBall()    // C# methods are upper-case by convention 
{
    transform.position += Vector3.right * currentDirection * Time.deltaTime;
}

檢查與哪種類型的球發生碰撞的方法不是很安全。 我建議您使用一個枚舉來區分球的大小。

public enum BallSizes { Largest, Large, Medium, Small, Smallest };    // The different possible values
public BallSize size = BallSizes.Largest;                             // The balls current size, the biggest size by default

這還允許您將y軸力值存儲在匹配的數組中,並且無需使用開關或else-if即可輕松訪問它們:

private float[] forcesY = new float[]{ 11.5f, 10.5f, 9f, 8f, 7f };

void SetBallSpeed() 
{
    forceX = 2.5f;
    forceY = forcesY[(int)size];
}

我認為您遇到的問題是球不分裂而造成的。
碰撞時,您可以通過檢查其標記來檢測與之碰撞的球的類型。 但是您總是使用相同的預制件實例化新球,而我從未見過您更改標簽。 那么,您要制造哪種類型的球?
如果您使用上述方法,則只需分配一個通用標簽“ Ball”,然后使用BallSizes-enum處理其余的標簽。 創建新球時,可以執行以下操作:

[SerializedField]            // The SerializedField property makes it show up in the inspector, even though it is private
private Ball ballPrefab;     // Attention: Type "Ball"

public void IsHit()          // Method to execute upon rocket collision
{
    if(ball.size != BallSizes.Smallest)
    {
        Ball leftBall = Instantiate(ballPrefab).  // Notice that, when you assign you prefab as Type "Ball", you directly get the Ball-Component as the return value.
        leftball.direction = -1;
        leftball.size = (BallSizes)(size + 1);    // Add one to size, to get get the next enum value, which is the next smaller size.

        Ball rightBall = ....                     // Do same stuff for the right ball
    }

    Destroy(this.gameObject);
}

我不知道您打算如何可視化球的類型,但是您可能想添加一個float[] ballScales ,用它來縮小球的實際大小,例如: leftBall.transform.localScale = Vector3.one * ballScales[(int)size]

最后,碰撞無法正常工作的另一個原因可能是,您在兩個不同的地方進行了處理。 如果在檢測到與球的碰撞后消滅了火箭,則球還沒有發生任何變化。 如果球隨后檢查碰撞,則很可能找不到火箭,因為您已經摧毀了它。
解決此問題的一種干凈方法是讓火箭將碰撞通知球:

void OnTriggerEnter2D(Collider2D target) 
{
    if(target.tag == "Top")
        Destroy(gameObject);
    else if(target.tag == "Ball")
    {
        target.GetComponent<Ball>().IsHit();    // We know this component should exist when the object is tagged "Ball"
        Destroy(gameobject);
    }
}

然后,您可以將其從球撞中刪除,並將其縮短為:

void OnTriggerEnter2D (Collider2D target) 
{
    if(target.tag == "Ground")    
        ball.velocity = new Vector2(0, forceY);

    if(target.tag == "Right Wall" || target.tag == "Left Wall")
        direction *= -1;    // Inverts the direction, + <-> -
}

ew,好多了。
我希望這仍然有意義,並且回答的問題多於提出的問題。
編碼愉快!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM