//tips
//UIでのオブジェクト操作
UIのドラッグ機能をスティックがわりに使い、プレイヤーの移動地点指定するオブジェクトを操作し、ドラッグを話した最終地点で、プレイヤーとオブジェクトが入れ替わる機能を実装する。
現状ではUI操作がうまくGhost側に反映されず、オブジェクトが動いていない。Debug.Log(directionfix)はきちんと座標を表示させているので、directionfixの受け取りがうまくいっていないことがわかる。スクリプトを見直すとReceiveEventGhost receiveEventGhostがうまく貼り付けられていなかったので修正。子要素にしたカプセルもきちんと動くようになった。
きちんと稼働しているが、playerghostのrigidbody周りでエラー表示が出ているので、改善していく。
playerghostにrigidbodyをつけず、transform.positionのみで動かすコードに変えてみる。こちらでもうまくいったので、プレイヤーに施していたコライダーのisTriggerを切り替えるGhostmode.isTriggerの記述を削除する。
また、UIのドラッグで距離が生じている場合のみghostの移動処理を行うためif(receiveEventGhost.distance != 0 )でドラッグ状態と認識されているが距離が生じていない状態は除外するようにした。
これで全てのエラー要因はなくせた。
PlayerWarpとReceiveEventGhostのスクリプトは下記でプレイヤーはrigidbodyあり、ghostはなしでコライダーにisTriggerをつけている。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerWarp : MonoBehaviour
{
public float speed = 3.0f; //プレイヤーの動くスピード
//private Vector3 Player_pos; //プレイヤーのポジション
private Rigidbody rigd;
[SerializeField]
ReceiveEventGhost receiveEventGhost;
[SerializeField]
GameObject playerghost;
//Collider Ghostmode;
void Start()
{
//Player_pos = GetComponent<Transform>().position; //最初の時点でのプレイヤーのポジションを取得
//rigd = playerghost.GetComponent<Rigidbody>(); //プレイヤーのRigidbodyを取得
//Ghostmode = GetComponent<Collider>();
}
public void GhostActive()
{
//Ghostmode.isTrigger = true;
playerghost.SetActive(true);
}
public void GhostDeactive()
{
transform.position = playerghost.transform.position;
playerghost.SetActive(false);
//Ghostmode.isTrigger = false;
}
void Update()
{
if (receiveEventGhost.onDrag)
{
if (receiveEventGhost.distance != 0)
{
playerghost.transform.rotation = Quaternion.LookRotation(receiveEventGhost.directionfix);
//rigd.position = transform.position + receiveEventGhost.directionfix * 3.0f;
playerghost.transform.position = transform.position + receiveEventGhost.directionfix * 3.0f;
}
}
/*
if (receiveEvent.onghost)//ボタンの移動計算が終了してからの動作にしたいので
{
transform.rotation = Quaternion.LookRotation(receiveEvent.directionfix);
//rigd.velocity = transform.forward * speed;
rigd.position = transform.position + transform.forward * 3.0f;
receiveEvent.onflash = false;
}
*/
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class ReceiveEventGhost : MonoBehaviour
{
Vector3 originpos;
Vector3 movepos;
Vector3 beforemovepos;
public Vector3 heading;
Vector3 direction;
public Vector3 directionfix;
public float distance;
PlayerWarp playerWarp;
//public bool onflash = false;
//bool cooldown = false;
//float countTime = 0;
//[SerializeField]
//int maxtime = 3;
public bool onDrag = false;
private void Start()
{
Transform transform = GetComponent<RectTransform>();
originpos = transform.position;
beforemovepos = originpos;
}
void Update()
{
if (onDrag)
{
movepos = transform.position;
Dragsimulate();
Debug.Log("計算開始");
}
/*
if (cooldown)
{
countTime += Time.deltaTime; //スタートしてからの秒数を格納
GetComponent<Image>().fillAmount = countTime / maxtime;
if (countTime >= 3.0f)
{
cooldown = false;
countTime = 0;
}
}
*/
}
public void MyDragIn()//pointerdown
{
playerWarp = GameObject.FindGameObjectWithTag("Player").GetComponent<PlayerWarp>();
playerWarp.GhostActive();
onDrag = true;
}
public void MyDragUI()//Drag
{
transform.position = Input.mousePosition;
/*
movepos = transform.position;
Dragsimulate();
transform.position = originpos;
*/
/*
if (cooldown != true)
{
transform.position = Input.mousePosition;
}
*/
}
public void MyDragExit()//pointerupへ
{
//cooldown = true;
transform.position = originpos;
playerWarp.GhostDeactive();
onDrag = false;
}
public void Dragsimulate()
{
heading = movepos - beforemovepos;
distance = heading.magnitude;
direction = heading / distance;
Debug.Log(direction);
directionfix = new Vector3(direction.x, 0, direction.y);//2dから3dへ変換
Debug.Log(directionfix);
beforemovepos = movepos;
}
}
UIのghostへの動作反映が歪なので、修正していく。歪というのは少しの手ぶれがオブジェクトに大きな影響を与えること、フレームの始まりと終わりの値の決まり方次第で方向が真逆に変わってしまうことなどがある。
playerghost.transform.position = transform.position + receiveEventGhost.directionfix * 3.0f;の動作にうまく動きの補完を入れることで滑らかに移動させていけないか考える。
現在はUIのupdateメソッドの読み出しタイミングでDragsimulateが読み込まれ、directionfixというベクトルを算出し、そのベクトルをreceiveEventGhost.directionfixという形でplayerghost.transform.positionに加算している。
void Update()
{
if (onDrag)
{
movepos = transform.position;
Dragsimulate();
Debug.Log("計算開始");
}
public void Dragsimulate()
{
heading = movepos - beforemovepos;
distance = heading.magnitude;
direction = heading / distance;
Debug.Log(direction);
directionfix = new Vector3(direction.x, 0, direction.y);//2dから3dへ変換
Debug.Log(directionfix);
beforemovepos = movepos;
}
下記のupdate,fixedupdateの違い、補間移動のサイトを参照し、変更を加える。
https://gametukurikata.com/basic/smoothmove
上記を参考にし補完移動を導入する。また、移動後にプレイヤーとghostで位置ズレする場合も見られたのでplayerghost.transform.position = transform.position;をif (receiveEventGhost.onDrag)がオフの際に追加。
前半の通常の動作と後半のVector3.Lerp動作を見比べる。
今回はVector3.Lerpがなくても大丈夫そう。修正したスクリプトは下記に記載する。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerWarp : MonoBehaviour
{
public float speed = 3.0f; //プレイヤーの動くスピード
//private Vector3 Player_pos; //プレイヤーのポジション
private Rigidbody rigd;
[SerializeField]
ReceiveEventGhost receiveEventGhost;
[SerializeField]
GameObject playerghost;
//Collider Ghostmode;
void Start()
{
//Player_pos = GetComponent<Transform>().position; //最初の時点でのプレイヤーのポジションを取得
//rigd = playerghost.GetComponent<Rigidbody>(); //プレイヤーのRigidbodyを取得
//Ghostmode = GetComponent<Collider>();
}
public void GhostActive()
{
//Ghostmode.isTrigger = true;
playerghost.SetActive(true);
}
public void GhostDeactive()
{
transform.position = playerghost.transform.position;
playerghost.SetActive(false);
//Ghostmode.isTrigger = false;
}
void Update()
{
if (receiveEventGhost.onDrag)
{
if (receiveEventGhost.distance != 0)
{
playerghost.transform.rotation = Quaternion.LookRotation(receiveEventGhost.directionfix);
//rigd.position = transform.position + receiveEventGhost.directionfix * 3.0f;
playerghost.transform.position = playerghost.transform.position + receiveEventGhost.directionfix * 0.1f;
//Vector3 targetposition = playerghost.transform.position + receiveEventGhost.directionfix * 3.0f;
//playerghost.transform.position = Vector3.Lerp(playerghost.transform.position, targetposition,Time.deltaTime);
//Debug.Log("playerghost.transform.position" + playerghost.transform.position);
}
}
else
{
playerghost.transform.position = transform.position;
}
/*
if (receiveEvent.onghost)//ボタンの移動計算が終了してからの動作にしたいので
{
transform.rotation = Quaternion.LookRotation(receiveEvent.directionfix);
//rigd.velocity = transform.forward * speed;
rigd.position = transform.position + transform.forward * 3.0f;
receiveEvent.onflash = false;
}
*/
}
}