Unity-什么是OOP-空引用异常



我是统一和面向对象编程的新手。最近我试图克隆Cube Surfer手机游戏。在我看来,基本的想法是这样的;

-当我们触发到由脚本组成的可折叠多维数据集时,它将作为子对象属于主多维数据集父对象,然后触发的多维数据集将被销毁。(定位后)

-稍后,当这些重复的子对象(多维数据集)进入其他可收集多维数据集的触发区域时,它们也会做同样的事情(这些将是相同的预制件,但尚未创建预制件)

我正在尝试收集(创建它的位置的克隆并销毁对象)多维数据集。对于第一个立方体,我在下面的移动脚本中添加了一些代码。

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

工作时没有出错,但后来,我将相同的方法应用于可收集的多维数据集脚本。

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

而且,我在ontrigenerter方法中的每一行都有nullexception错误,然后,我用问号更改(添加)了行。所以,我得到

ArgumentException:GetComponent要求请求的组件"GameObject"派生自MonoBehavior或component,或者是一个接口。UnityEngine.GameObject.GetComponentInParent[T](System.Boolean includeInactive)(位于:0)UnityEngine.GameObject.GetComponentInParent[T]()(位于:0)UpNdown.OnTiggerEnter(UnityEngine.Clinder other)

我想,我理解OOP实例的想法,即场景中的对象是实例脚本有其自身的价值。。。但我不明白,当我在一个实例上操作时,为什么它在内存中为空:(如果PC无法访问如何实例化对象?

对不起,我写了这么长,但我又快崩溃了。我不想因为再次面临这个问题而退出

谢谢你的回答,已经很感激了:)

GameObject不是组件(它是连接到它的所有组件的容器!)

=>使用GetComponentGetComponentInParent根本无法获得它。(顺便说一句,注意GetComponentInParent在构建层次结构之前首先开始对这个对象本身进行搜索,所以无论哪种方式,这都不是你想要使用的)。


您想要的只是transform.parent来获得该脚本所附对象的父对象的Transform组件(假设您的代码的其余部分完成了它应该做的事情)

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

或者,由于您的父对象上有特定组件,因此您也可以执行

// Instead directly get this component
var parentMovement = GetComponentInParent<Movement>();
// Then wherever needed access the transform through it
var parentTransform = parentMovement.transform;
...

不过我很确定,反过来它会更有效,因为你已经确切地知道你在哪个父级上搜索组件了


或者-这可能是最好的选择-立即缓存父信息一次

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

Ty先生,我的第一个代码与您的第一个答案几乎相同,但没有再次工作,至少有错误。


private Transform parentTransform;
private void Awake ()
{
if(! parentMovement) parentMovement = GetComponentInParent<Movement>();
parentTransform = parentMovement.transform;
} 

但这起到了作用,我想问题是我需要将实例定义为类,这样它们就不会在触发函数上立即消失,或者直接我需要将它们定义为类。

无论如何,谢谢你德雨果现在需要解决不同的问题:D

相关内容

  • 没有找到相关文章

最新更新