序章
私は現在、GameObjectのポイントアンドクリックの動作を制御するスクリプト(UnityのC#スクリプト)を作成しようとしています。
本質的に、プレーヤーは、画面をクリックするだけで熱気球を制御します。これにより、オブジェクトは加速し始め、クリックの位置に向かって移動します。クリック位置の特定の距離にあるとき、熱気球は反対方向に加速し始め(したがって減速し)、クリックの位置で正確に完全に停止するはずです。
私はすでに完全に機能するコメント付きのスクリプト(この投稿の下部にあります)を作成しました。このスクリプトは、GameObjectを一定の速度でクリックの位置に向かって移動し、特定の距離内にあるとき、その時点で停止します。
また、加速しながらクリックの位置に向かって移動する、個別に完全に機能するスクリプトを作成しました(そのような小惑星を突き出す動作を取得します)。これは、投稿の下部にもあります。
問題
今私が直面している問題は、これら2つの動作を取り、それらを1つの動作スクリプトとして実装できる解決策を見つけるためにかなり長い間取り組んできたということです。つまり、熱気球は加速動作をします。また、ここにあるこの視覚的な例とまったく同じように、速度を落とし、目標位置で停止します。
質問
私の質問は次のようになります:
一定の速度だけでなく、方程式に加速度も含まれている場合、どのようにして到着動作を作成できますか?私はこの問題を調査し、自分自身の解決策を試してみましたが、私が行うことは何も期待どおりに機能していないようです。
スクリプトの添付ファイル
到着動作を伴う一定速度でのポイントアンドクリックの動き
using UnityEngine;
using System.Collections;
public class PlayerControl : MonoBehaviour
{
// Fields
Transform cachedTransform;
Vector3 currentMovementVector;
Vector3 lastMovementVector;
Vector3 currentPointToMoveTo;
Vector3 velocity;
int movementSpeed;
Vector3 clickScreenPosition;
Vector3 clickWorldPosition;
float slowingDistance = 8.0f;
Vector3 desiredVelocity;
float maxSpeed = 1000.0f;
// Use this for initialization
void Start ()
{
cachedTransform = transform;
currentMovementVector = new Vector3(0, 0);
movementSpeed = 50;
currentPointToMoveTo = new Vector3(0, 0);
velocity = new Vector3(0, 0, 0);
}
// Update is called once per frame
void Update ()
{
// Retrive left click input
if (Input.GetMouseButtonDown(0))
{
// Retrive the click of the mouse in the game world
clickScreenPosition = Input.mousePosition;
clickWorldPosition = Camera.main.ScreenToWorldPoint(new Vector3(clickScreenPosition.x, clickScreenPosition.y, 0));
currentPointToMoveTo = clickWorldPosition;
currentPointToMoveTo.z = 0;
// Calculate the current vector between the player position and the click
Vector3 currentPlayerPosition = cachedTransform.position;
// Find the angle (in radians) between the two positions (player position and click position)
float angle = Mathf.Atan2(clickWorldPosition.y - currentPlayerPosition.y, clickWorldPosition.x - currentPlayerPosition.x);
// Find the distance between the two points
float distance = Vector3.Distance(currentPlayerPosition, clickWorldPosition);
// Calculate the components of the new movemevent vector
float xComponent = Mathf.Cos(angle) * distance;
float yComponent = Mathf.Sin(angle) * distance;
// Create the new movement vector
Vector3 newMovementVector = new Vector3(xComponent, yComponent, 0);
newMovementVector.Normalize();
currentMovementVector = newMovementVector;
}
float distanceToEndPoint = Vector3.Distance(cachedTransform.position, currentPointToMoveTo);
Vector3 desiredVelocity = currentPointToMoveTo - cachedTransform.position;
desiredVelocity.Normalize();
if (distanceToEndPoint < slowingDistance)
{
desiredVelocity *= movementSpeed * distanceToEndPoint/slowingDistance;
}
else
{
desiredVelocity *= movementSpeed;
}
Vector3 force = (desiredVelocity - currentMovementVector);
currentMovementVector += force;
cachedTransform.position += currentMovementVector * Time.deltaTime;
}
}
加速を使用してポイントアンドクリックの動きをしますが、到着動作はありません
using UnityEngine;
using System.Collections;
public class SimpleAcceleration : MonoBehaviour
{
Vector3 velocity;
Vector3 currentMovementVector;
Vector3 clickScreenPosition;
Vector3 clickWorldPosition;
Vector3 currentPointToMoveTo;
Transform cachedTransform;
float maxSpeed;
// Use this for initialization
void Start ()
{
velocity = Vector3.zero;
currentMovementVector = Vector3.zero;
cachedTransform = transform;
maxSpeed = 100.0f;
}
// Update is called once per frame
void Update ()
{
// Retrive left click input
if (Input.GetMouseButtonDown(0))
{
// Retrive the click of the mouse in the game world
clickScreenPosition = Input.mousePosition;
clickWorldPosition = Camera.main.ScreenToWorldPoint(new Vector3(clickScreenPosition.x, clickScreenPosition.y, 0));
currentPointToMoveTo = clickWorldPosition;
// Reset the z position of the clicking point to 0
currentPointToMoveTo.z = 0;
// Calculate the current vector between the player position and the click
Vector3 currentPlayerPosition = cachedTransform.position;
// Find the angle (in radians) between the two positions (player position and click position)
float angle = Mathf.Atan2(clickWorldPosition.y - currentPlayerPosition.y, clickWorldPosition.x - currentPlayerPosition.x);
// Find the distance between the two points
float distance = Vector3.Distance(currentPlayerPosition, clickWorldPosition);
// Calculate the components of the new movemevent vector
float xComponent = Mathf.Cos(angle) * distance;
float yComponent = Mathf.Sin(angle) * distance;
// Create the new movement vector
Vector3 newMovementVector = new Vector3(xComponent, yComponent, 0);
newMovementVector.Normalize();
currentMovementVector = newMovementVector;
}
// Calculate velocity
velocity += currentMovementVector * 2.0f * Time.deltaTime;
// If the velocity is above the allowed limit, normalize it and keep it at a constant max speed when moving (instead of uniformly accelerating)
if (velocity.magnitude >= (maxSpeed * Time.deltaTime))
{
velocity.Normalize();
velocity *= maxSpeed * Time.deltaTime;
}
// Apply velocity to gameobject position
cachedTransform.position += velocity;
}
}