//tips
//アイテムの使用
Inventoryのアイテムをクリックしたら任意の場所に該当アイテムを生成する方法を確認する。
今回はinventoryのアイテムをクリックしたらrodをプレイヤーの手元に出現させるスクリプトを考える。
Dropしているrodを取得するスクリプトは下記なのでこちらをベースに考えていく。最初から接触している状態で呼び出すのでflagは必要なくinstantiateする場所の指定を適切にすれば問題ない。 m_Colliderには子要素となるrodのColliderを入れてあげることで接触反応を管理する。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class OnTriggerParent : MonoBehaviour
{
bool flag = false;
Animation anim;
[SerializeField] private Collider m_Collider;
private void Update()
{
if (flag)
{
if (Input.GetKeyDown(KeyCode.Space))
{
anim = this.GetComponent<Animation>();
anim.Play();
}
}
}
public void HitStart()
{
m_Collider.enabled = true;
}
public void HitEnd()
{
m_Collider.enabled = false;
}
void OnTriggerStay(Collider other)
{
//接触しているオブジェクトのタグが"Player"のとき
if (other.CompareTag("Player"))
{
this.transform.parent = other.transform;
Transform myTransform = this.transform;
// 座標を取得
transform.localPosition = new Vector3(0.7f, 0.3f, 0.3f);
Debug.Log(myTransform.position);
flag = true;
m_Collider.enabled = false;
}
}
}
今回はprefabからプレイヤーの子要素として生成するのでその部分は考える必要がある。OnTriggerStay(Collider other)の中身をInstantiateで肩代わりして、flag = true;にするメソッドがあれば良い。
下記のスクリプトを記載してiconオブジェクトにアタッチした。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Rodcom : MonoBehaviour
{
[SerializeField] private Transform p_pos;
[SerializeField] private Collider m_Collider;
public GameObject prefabrod;
Transform rod_pos;
OnTriggerParent onTriggerParent;
public void GetPPos()
{
Instantiate(prefabrod);
prefabrod.transform.parent = p_pos;
prefabrod.transform.localPosition = new Vector3(0.7f, 0.3f, 0.3f);
onTriggerParent.flag = true;
m_Collider.enabled = false;
}
}
発生したエラーは2つ。
Setting the parent of a transform which resides in a Prefab Asset is disabled to prevent data corruption (GameObject: 'rodPivot').
UnityEngine.Transform:set_parent(Transform)
Rodcom:GetPPos() (at Assets/Rodcom.cs:31)
UnityEngine.EventSystems.EventSystem:Update()
NullReferenceException: Object reference not set to an instance of an object
Rodcom.GetPPos () (at Assets/Rodcom.cs:36)
これはprefabObjをそのまま子オブジェクトに設定しようとしているときに起こるエラーのようでinstantiateしたオブジェクトをきちんと変数に入れ、そのオブジェクトを扱うようにしなければならない。なので下記のように修正。
GameObject gameObj = Instantiate(prefabrod) as GameObject;
gameObj.transform.parent = p_pos;
gameObj.transform.localPosition = new Vector3(0.7f, 0.3f, 0.3f);
これによりrodのポジションは適切な場所に表示されるようになった。
ただ、 onTriggerParent.flag = true;の部分でエラーが出ている。
NullReferenceException: Object reference not set to an instance of an object
Rodcom.GetPPos () (at Assets/Rodcom.cs:25)
onflag.FlagOn();などのようにOnTriggerParentスクリプトを修正したが、なぜかrodpivodのprefabにアタッチされているOnTriggerParentのスクリプトが読み込まれていない。Updateの部分にDebug.Log(flag);を記載しても反応なし。
これはDebug.Log(flag);が反応しなかったのはVisual studioでのコード変更がUnityに反映されていないだけだった。各スクリプトで再度saveしたら反映された。
public void GetPPos()
{
GameObject gameObj = Instantiate(prefabrod) as GameObject;
gameObj.transform.parent = p_pos;
gameObj.transform.localPosition = new Vector3(0.7f, 0.3f, 0.3f);
OnTriggerParent onflag = onTriggerParent.GetComponent<OnTriggerParent>();
onflag.FlagOn();
m_Collider.enabled = false;
Debug.Log(onTriggerParent);
Debug.Log("flag確認");
}
}
よく考えたら生成されるgameObjにスクリプトはアタッチされているのでもっとシンプルにできた。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Rodcom : MonoBehaviour
{
[SerializeField] private Transform p_pos;
[SerializeField] private Collider m_Collider;
public GameObject prefabrod;
public void GetPPos()
{
GameObject gameObj = Instantiate(prefabrod) as GameObject;
gameObj.transform.parent = p_pos;
gameObj.transform.localPosition = new Vector3(0.7f, 0.3f, 0.3f);
OnTriggerParent onflag = gameObj.GetComponent<OnTriggerParent>();
onflag.FlagOn();
m_Collider.enabled = false;
Debug.Log("flag確認");
}
}
こちらでプレイヤーの定位置にアイテムの生成はできた。
問題はspaceボタンを押すたびにUIが開閉し、それにより、ボタンが押されたことになり、GetPPos()が呼ばれてしまうよう。
一度生成されたら2度呼べなくするように設定するのがシンプルなのでスクリプトを変更。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Rodcom : MonoBehaviour
{
[SerializeField] private Transform p_pos;
[SerializeField] private Collider m_Collider;
public GameObject prefabrod;
bool isntgameobj = true;
public void GetPPos()
{
GameObject gameObj;
if (isntgameobj)
{
gameObj = Instantiate(prefabrod) as GameObject;
gameObj.transform.parent = p_pos;
gameObj.transform.localPosition = new Vector3(0.7f, 0.3f, 0.3f);
OnTriggerParent onflag = gameObj.GetComponent<OnTriggerParent>();
onflag.FlagOn();
m_Collider.enabled = false;
Debug.Log("flag確認");
isntgameobj = false;
}
}
}