im kind of newbie to unity and object oriented programming. Recently im trying to clone Cube Surfer mobile game. Basic idea from my view is this ;
-When we triggered to collactable cubes which consist script will be duplicated and it will be belong the main cube parent as child object then triggered cube will be destroyed.(After positioning)
-Later this duplicate child objects(cubes) will do the same when they enter trigger area of other collectable cubes(those will be the same prefab but did not yet create a prefab)
Im trying to collect(create a clone of it position and destroy the object) cubes. For first cube, I added some code to my movement script which is below.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Movement : MonoBehaviour
{
public GameObject addup;
Rigidbody rb;
float controlSpeed = 1.25f;
float forwardMovementSpeed = 10f;
private Vector3 axisGet;
float deathTime;
public int collected;
// Start is called before the first frame update
void Start()
{
rb = gameObject.GetComponent<Rigidbody>();
collected = 0;
}
// Update is called once per frame
void FixedUpdate()
{
axisGet = new Vector3(0, 0, Input.GetAxis("Horizontal"));
rb.MovePosition(transform.position Vector3.left * forwardMovementSpeed * Time.deltaTime axisGet * controlSpeed * Time.deltaTime);
}
private void OnTriggerEnter(Collider other)
{
if(other.tag=="add up")
{
gameObject.transform.position = Vector3.up;
var newObject = Instantiate(addup.gameObject, Vector3.zero, Quaternion.identity);
newObject.transform.parent = transform;
newObject.transform.position = gameObject.transform.position Vector3.down;
Destroy(other.gameObject);
newObject.GetComponent<BoxCollider>().isTrigger = false;
collected ;
}
}
}
WORKED WITHOUT ERROR BUT THEN, I applied the same method to collectable cubes scripts.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class UpNdown : MonoBehaviour
{
void Start()
{
}
// Update is called once per frame
void Update()
{
}
private void OnTriggerEnter(Collider other)
{
if (other.tag == "add up")
{
GameObject parentTransform;//?????????
parentTransform = gameObject.GetComponentInParent<GameObject>(); //get first cube component
parentTransform.transform.position = Vector3.up; //first cube one unit up
GameObject newObject; // ?????????
newObject = Instantiate(other.gameObject, Vector3.zero, Quaternion.identity) as GameObject; //???????????
Debug.Log(newObject);
var collect = parentTransform.GetComponent<Movement>().collected;
if (other != null)
{
Destroy(other.gameObject); //destroy triggered collactable
}
newObject.transform.parent = parentTransform.transform; //setting parent to new cube
newObject.transform.position = parentTransform.transform.position Vector3.down * (collect 1); //setting position of new cube
newObject.GetComponent<BoxCollider>().isTrigger = false; //prepare the below cubes(new cubes) for trigger with other collactable cubes
collect ;
}
}
}
And, I had nullexception error in every line in ontriggerenter method then, I changed(added) the lines with question marks. So, I get
ArgumentException: GetComponent requires that the requested component 'GameObject' derives from MonoBehaviour or Component or is an interface. UnityEngine.GameObject.GetComponentInParent[T] (System.Boolean includeInactive) (at :0) UnityEngine.GameObject.GetComponentInParent[T] () (at :0) UpNdown.OnTriggerEnter (UnityEngine.Collider other)
I thought, I understood the OOP instance idea which objects in the scenes are instances scripts has their own value... but i dont understand that while I was operating on a instance why it is null in the memory :((((((((((((( if PC can't access how instantiates the object ?
SORRY I WRITE THIS LONG BUT IM ABOUT THE EDGE AGAIN I DON'T WANT TO QUIT BECAUSE OF FACING THIS PROBLEM AGAIN
TY FOR YOUR ANSWERS, ALREADY APPRECIATED :)
CodePudding user response:
GameObject
is no component (it is rather a container of all components attached to it!)
=> you can't get it using GetComponent
or GetComponentInParent
at all. (Btw Note that GetComponentInParent
starts the search on this object itself first before bubling up the hierarchy so either way this isn't what you want to use).
What you want is simply transform.parent
to get the Transform
component of the parent object of the object this script is attached to (assuming the rest of your code does what it should)
private void OnTriggerEnter(Collider other)
{
// Rather use CompareTag instead of string ==
// The latter silently fails in case of typos making your debugging life miserabel
// it is also slightly less efficient
if (!other.CompareTag("add up")) return;
// Get the parent of this object
var parentTransform = transform.parent;
// Cache this you will need it later see below
var parentMovement = parentTransform.GetComponent<Movement>();
var collect = parentMovement.collected;
parentTransform.position = Vector3.up;
// By using the correct type you want later you can skip GetComponent
var newObjectCollider = Instantiate(other, Vector3.zero, Quaternion.identity);
Debug.Log(newObjectCollider);
Destroy(other.gameObject);
newObjectCollider.transform.parent = parentTransform;
newObjectCollider.transform.position = parentTransform.position Vector3.down * (collect 1);
newObjectCollider.isTrigger = false;
// This does absolutely nothing. Numeric values are passed by value and there is no connection
// between your local variable and the component you got it from
//collect ;
// you probably rather want to increase
parentMovement.collected ;
}
Or alternatively since you anyway have a specific component on your parent object you could also do
// Instead directly get this component
var parentMovement = GetComponentInParent<Movement>();
// Then wherever needed access the transform through it
var parentTransform = parentMovement.transform;
...
I'm quite sure though that the other way round it is more efficient since you already know exactly which parent you are searching the component on.
Or - and this would probably be the best option - cache that parent information once right away:
// If possible already reference this vis the Inspector
[SerializeField] private Movement parentMovement;
private Transform parentTransform;
private void Awake ()
{
if(! parentMovement) parentMovement = GetComponentInParent<Movement>();
parentTransform = parentMovement.transform;
}
CodePudding user response:
Ty sir my first code was nearly the same of your first answer but didn't work again at least for error.
private Transform parentTransform;
private void Awake ()
{
if(! parentMovement) parentMovement = GetComponentInParent<Movement>();
parentTransform = parentMovement.transform;
}
But this worked, I guess the problem I need to define instances to class so they don't disappear instantly on the trigger function or direct I need to define them to class.
Anyway, thank you derHugo now need to solve different problems :D