- Home /
Making a moving gameobject approach and stop at a target (arrival behaviour)
Hello everyone :)
Introduction
I am currently trying to create a script which controls point and click behaviour for a GameObject.
In essence, the player will - in the end - control a hot air balloon by simply clicking on the screen, whereby the object will start to accelerate and move toward the position of the click. When at a specific distance of the click position, the hot air balloon should then start to accelerate in the opposite direction (thus decelerating) and come to a complete halt exactly at the position of the click.
I have already created a fully functional and commented script (found at the bottom of this post), which simply moves a GameObject towards the position of a click at a constant speed, and then when within a specific distance, starts to slow down until stopping at the point.
I have also created a separately and fully functional script which moves toward the position of a click while accelerating (getting that kind of asteroids thrusting behaviour). This can also be found at the bottom of the post.
The Problem
Now the problem that I'm facing is that I've been working quite a while now to find a solution where you can take these two behaviours and implement them as one working script, that is, the hot air balloon have the accelerating behaviour while also slowing down and stopping at a target position, exactly like this visual example found here:
Visual Arrival Behaviour Demonstration
The Question
My question then becomes:
how can you make the arrival behaviour not only using constant speeds, but with acceleration included in the equation as well?
Script attachments
Point and click movement at constant speeds with arrival behaviour
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;
}
}
Point and click movement using acceleration but no arrival behaviour
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;
}
}
Your answer
Follow this Question
Related Questions
The name 'Joystick' does not denote a valid type ('not found') 2 Answers
Enemy Damage 2 Answers
AI using Javascript 1 Answer
Enemies Moving Through Terrain Help 1 Answer
movement script 2 Answers