//tips
//再ドロップなどのアイテム処理
GolemSoulCounterをタップすることで先に作成したカウントをマイナスし、ドロップアイテムをプレイヤーの意思でドロップできるよう機能を追加する。
まずはGolemSoulのimage自体にボタンコンポーネントを追加。
GolemSoulCounterスクリプトにカウントのマイナス処理を追加し、それをボタンに設定。
public void SoulCounterminus()
{
count--;
}
さらにGolemSoulオブジェクトそのものにアタッチされているGolemSouldropスクリプトに下記を加える。
public void ReDropgolemitem()
{
targetobj = null;
Vector3 repos = new Vector3(0, 0, 2);
this.transform.position = transform.position + repos;
this.gameObject.SetActive(true);
}
Imageに貼り付けても反応せず、要因を探していたらTextオブジェクトの範囲がimageよりも上にかぶさっていることがわかった。Textオブジェクトにボタンコンポーネントをアタッチした。
無事に球のオブジェクトを再ドロップさせ、カウントもマイナスにできたがキャラクターの前に必ずしもドロップできないので、transfordforwardなどで位置の取得を考える。
Vector3 repos = targetobj.transform.forward * 2;としたが、z方向に二マス分移動した値に生成してしまう。
キャラクター前方を取得するのにはrigidbodyを使わなければならない可能性を考え動作させてみたら、アクションとしてはrigidbodyを使った方が良さそうなことはわかったが、別のところに問題がありそうなことがわかってきた。targetobj = null;にしてしまうとゴーレムを倒した場所を基準に球が生成されてしまう問題がある。
this.gameObject.SetActive(true);と同時にtargetobjの位置を参照し、移動させていたことを考えると、ReDropgolemitem()メソッド内の処理の順番を変更することで対応できそうなので試してみる。
きちんとキャラクターの前方に落ちたり、落ちなかったりするので、別のコードで試してみる。落ちる場所を変更しなければならないの保持キャラクターが再度取得してしまうのを避けるためなので、その再度取得をできなくしておけば、球をそのまま落下させれば良いことになる。
Boolを導入して前回のtargetの場合は接触対象はから外すようにした。ただ、同じポジションに生成するとキャラクターが位置被りによって弾け飛んでしまったので、下記のように頭上生成しつつ、rigidbodyの力を加えて前方に転がすようにした。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GolemSouldrop : MonoBehaviour
{
GameObject targetobj;
public bool dropflag=false;
[SerializeField]
GolemSoulCounter golemSoulCounter;
Rigidbody rb;
bool stayitem=false;
void OnCollisionEnter(Collision collision)
{
if (collision.gameObject.tag == ("Player"))
{
if(collision.gameObject != targetobj)
{
targetobj = collision.gameObject;
this.gameObject.SetActive(false);
//Destroy(this.gameObject);
golemSoulCounter.SoulCounterplus();
stayitem = false;
}
}
}
void Start()
{
rb = this.GetComponent<Rigidbody>();
}
void Update()
{
Vector3 offset = new Vector3(0, 3, 0);
if (!dropflag && targetobj!=null&& !stayitem)
{
this.transform.position = targetobj.transform.position + offset;
}
}
public void Dropgolemitem()
{
this.gameObject.SetActive(true);
}
public void ReDropgolemitem()
{
stayitem = true;
Vector3 offset = new Vector3(0, 3, 0);
this.transform.position = targetobj.transform.position + offset;
rb.velocity = targetobj.transform.forward * 2;
this.gameObject.SetActive(true);
}
}
次に獲得したGolemSoulの提出先を作成する。GolemSoulを1以上保有している時に特定の場所に立つことでUIの表示が現れ、yesを押すとGolemSoulを提出できるようにする。
まず透過させた円柱のコライダーのistrrigerをonにし、一定時間stayしていた場合にinvokeでpanelを表示できるようにする。
SoulPostTrrgerスクリプトを作成し、ontrrigerstayのメソッドを書いていく。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SoulPostTrrger : MonoBehaviour
{
private float _targetTime=3;
private float _time = 0;
[SerializeField]
GameObject GolemsoulPost;
private void OnTriggerStay(Collider other)
{
if (other.gameObject.tag == "Player")
{
_time += Time.fixedDeltaTime;//物理演算の処理内では固定フレームなので Time.deltaTimeはいまいちのよう
if (_time >= _targetTime)
{
OpenSoulPost();
_time = 0;
}
}
}
void OpenSoulPost()
{
GolemsoulPost.SetActive(true);
}
}
これで特定領域の滞在時間でUI表示させる機能はできた。待機時間が少し短かったので3秒にし、領域も広くした。
さらに継続して滞在すると再度UIが表示されるので領域外に一度出ないと再度UIが表示されないように OnTriggerExitも書き込んだ。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SoulPostTrrger : MonoBehaviour
{
private float _targetTime=3;
private float _time = 0;
[SerializeField]
GameObject GolemsoulPost;
bool stayflag=false;
private void OnTriggerStay(Collider other)
{
if (other.gameObject.tag == "Player")
{
_time += Time.fixedDeltaTime;//物理演算の処理内では固定フレームなので Time.deltaTimeはいまいちのよう
if (_time >= _targetTime)
{
if (!stayflag)
{
OpenSoulPost();
}
_time = 0;
}
}
}
private void OnTriggerExit(Collider other)
{
if (other.gameObject.tag == "Player")
{
stayflag = false;
}
}
void OpenSoulPost()
{
GolemsoulPost.SetActive(true);
stayflag = true;
}
public void CloseSoulPost()
{
GolemsoulPost.SetActive(false);
}
}
GolemSoulCounterスクリプトと連動させることで、カウントを減らすこともできたので、次はPostで管理する分の変数を作成し、その数がmaxになった時にゲームクリアシーンに移行するようにする。