c# - How to make an object seek and decelerate to a stop exactly on a specified position? -
introduction
i trying create script (c# script in unity) controls point , click behaviour gameobject.
in essence, player - in end - control hot air balloon clicking on screen, whereby object start accelerate , move toward position of click. when @ specific distance of click position, hot air balloon should start accelerate in opposite direction (thus decelerating) , come complete halt @ position of click.
i have created functional , commented script (found @ bottom of post), moves gameobject towards position of click @ constant speed, , then, when within specific distance, starts slow down until stopping @ point.
i have created separately , functional script moves toward position of click while accelerating (getting kind of asteroids thrusting behaviour). can found @ bottom of post.
the problem
now problem i'm facing i've been working quite while find solution can take these 2 behaviours , implement them 1 working script, is, hot air balloon have accelerating behaviour while slowing down , stopping @ target position, visual example found here:
visual arrival behaviour demonstration
the question
my question becomes:
how can make arrival behaviour not using constant speeds, acceleration included in equation well? i've tried research problem experimenting own solutions, nothing seems work quite way should.
script attachments
point , click movement @ constant speeds 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 initialization void start () { cachedtransform = transform; currentmovementvector = new vector3(0, 0); movementspeed = 50; currentpointtomoveto = new vector3(0, 0); velocity = new vector3(0, 0, 0); } // update called once per frame void update () { // retrive left click input if (input.getmousebuttondown(0)) { // retrive click of mouse in game world clickscreenposition = input.mouseposition; clickworldposition = camera.main.screentoworldpoint(new vector3(clickscreenposition.x, clickscreenposition.y, 0)); currentpointtomoveto = clickworldposition; currentpointtomoveto.z = 0; // calculate current vector between player position , click vector3 currentplayerposition = cachedtransform.position; // find angle (in radians) between 2 positions (player position , click position) float angle = mathf.atan2(clickworldposition.y - currentplayerposition.y, clickworldposition.x - currentplayerposition.x); // find distance between 2 points float distance = vector3.distance(currentplayerposition, clickworldposition); // calculate components of new movemevent vector float xcomponent = mathf.cos(angle) * distance; float ycomponent = mathf.sin(angle) * distance; // create 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 , click movement using acceleration 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 initialization void start () { velocity = vector3.zero; currentmovementvector = vector3.zero; cachedtransform = transform; maxspeed = 100.0f; } // update called once per frame void update () { // retrive left click input if (input.getmousebuttondown(0)) { // retrive click of mouse in game world clickscreenposition = input.mouseposition; clickworldposition = camera.main.screentoworldpoint(new vector3(clickscreenposition.x, clickscreenposition.y, 0)); currentpointtomoveto = clickworldposition; // reset z position of clicking point 0 currentpointtomoveto.z = 0; // calculate current vector between player position , click vector3 currentplayerposition = cachedtransform.position; // find angle (in radians) between 2 positions (player position , click position) float angle = mathf.atan2(clickworldposition.y - currentplayerposition.y, clickworldposition.x - currentplayerposition.x); // find distance between 2 points float distance = vector3.distance(currentplayerposition, clickworldposition); // calculate components of new movemevent vector float xcomponent = mathf.cos(angle) * distance; float ycomponent = mathf.sin(angle) * distance; // create new movement vector vector3 newmovementvector = new vector3(xcomponent, ycomponent, 0); newmovementvector.normalize(); currentmovementvector = newmovementvector; } // calculate velocity velocity += currentmovementvector * 2.0f * time.deltatime; // if velocity above allowed limit, normalize , keep @ constant max speed when moving (instead of uniformly accelerating) if (velocity.magnitude >= (maxspeed * time.deltatime)) { velocity.normalize(); velocity *= maxspeed * time.deltatime; } // apply velocity gameobject position cachedtransform.position += velocity; } }
adapt first script:
introduce variable velocity, in second script. set equal movementspeed in start(), , don't use movementspeed after that. do not proceed until works perfectly.
now introduce acceleration:
if (distancetoendpoint < slowingdistance) { velocity *= distancetoendpoint/slowingdistance; } else { velocity += direction * 2.0f * time.deltatime; }
Comments
Post a Comment