[英]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
您的代碼比需要的要復雜得多,因此很難找到實際的錯誤。
首先,您的moveLeft
和moveRight
互斥。 您只需要其中之一。 我想用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.