2d Trajectory Line Prediction not acurate - c#

I'm current facing a problem where in my trajectory line is very inaccurate
Please see the attached image below
Here's where it goes
Here's my code so far
private void Start()
{
line = new GameObject[maxDots];
for (int i = 0; i < line.Length; i++)
{
var go = GameObject.CreatePrimitive(PrimitiveType.Sphere);
go.transform.localScale = new Vector3(0.5f, 0.5f, 0.5f);
line[i] = go;
}
startPos = transform.position;
}
on my OnMouseUp is for shooting the ball
//TEMPORARY
private void OnMouseUp()
{
// Disable IsKenematic
GetComponent<Rigidbody2D>().isKinematic = false;
// Add the Force
Vector2 dir = startPos - (Vector2)transform.position;
GetComponent<Rigidbody2D>().AddForce(dir * force);
//Remove the script (not the gameobject)
Destroy(this);
}
And on my OnMouseDrag is for the ball to keep in radius cause I set a limit for the dragging of the ball
private void OnMouseDrag()
{
DisplayLine();
//Convert mouse potision to world position
Vector2 p = Camera.main.ScreenToWorldPoint(Input.mousePosition);
//Keep it in a certain radius
float radius = 1.8f;
Vector2 dir = p - startPos;
if (dir.sqrMagnitude > radius)
{
dir = dir.normalized * radius;
//Set position
transform.position = startPos + dir;
}
}
Here's my method of displaying the line
void DisplayLine()
{
line[0].transform.position = transform.position;
Vector3 v3 = transform.position;
float y = (forces * (home - transform.position)).y;
float t = 0.0f;
v3.y = 0.0f;
for(int i = 1; i < line.Length; i++)
{
v3 += forces * (home - transform.position) * spacing;
t += spacing;
v3.y = y * t + 0.5f * Physics2D.gravity.y * t * t + transform.position.y;
line[i].transform.position = v3;
}
}
What I am trying to do is that create a trajectory prediction line for my game I know I am almost there but still couldn't get the exact output that I want. Could someone help me. Thank you.

Use the same function to calculate both.
Then you won't have the problem also any change on trajectory calculation results in only one change not two.

Solved it
line[0].transform.position = transform.position;
Vector2 v2 = transform.position;
float y = (force *( startPos - (Vector2)transform.position)).y;
float t = 0.0f;
v2.y = 0.0f;
for(int i = 1; i < line.Length; i++)
{
v2 += force * (startPos - (Vector2)transform.position) * spacing;
t += spacing;
v2.y = y * t + 0.5f * Physics2D.gravity.y * t * t + transform.position.y;
line[i].transform.position = v2;
}
I need to change from vector3 to vector2 so I need to cast (vector2) between those transform.positions.y

Related

How to rotate around an object without using unity's built-in functions?

i want to rotate a cube around a 1x1 pipe with arrow keys. (left and right).
The problem is i cannot use built-in functions which sets transform's position and location directly. (Such as transform.lookAt, transform.Rotate or transform.RotateAround). Because I need the vector values of rotation's euler and position for multiple stuff before i modify the value of the transform i want to rotate.
I tried different techniques but no luck so far.
I tried using sin-cos for rotating but could not figure out how to make it work for both rotation and position.
_timer += Time.deltaTime * _larvaSpeed;
float x = -Mathf.Cos(_timer) * distanceBetweenCenter;
float y = Mathf.Sin(_timer) * distanceBetweenCenter;
Here is what i want to achieve. By pressing right or left, move and rotate the object around the pipe.
The result i want. (If i pressed right arrow key a litte bit).
I would appreciate any help. Thank you!
here is the solution using circle mathematics and I strongly recommended not use it, it's just to understand the circular move using circle equation as #FaTaLL ask in the comments
Circle equation...
(x1 - x2)^2 + (y1 - y2)^2 = r^2
x1, y1 is the cube position
x2, y2 is the pipe position
r is the distance between cube and pipe;
using UnityEngine;
public class Rotating : MonoBehaviour
{
public GameObject pipe;
public float Delta;
Vector3 nextpos;
bool compareY;
bool next;
int switchx;
float storeVarAxis;
float x, y, r;
private void Start()
{
next = true;
switchx = 1;
compareY = true;
x = transform.position.x - pipe.transform.position.x;
y = transform.position.y - pipe.transform.position.y;
storeVarAxis = y;
r = Mathf.Sqrt(x * x + y * y);
}
private void Update()
{
if (next)
{
if (compareY == true)
{
y -= Delta * Time.deltaTime;
if (y <= -storeVarAxis)
{
y = -storeVarAxis;
compareY = false;
switchx = -1;
}
}
else
{
y += Delta * Time.deltaTime;
if (y >= storeVarAxis)
{
y = storeVarAxis;
compareY = true;
switchx = 1;
}
}
float v = r * r - y * y;
x = Mathf.Sqrt(Mathf.Abs(v));
nextpos = new Vector3(pipe.transform.position.x + x * switchx, pipe.transform.position.y + y, transform.position.z);
next = false;
}
transform.position = Vector3.MoveTowards(transform.position, nextpos, 1f * Time.deltaTime);
if(Vector3.Distance(transform.position, nextpos) < .05) transform.position = nextpos;
if (transform.position.x.Equals(nextpos.x) && transform.position.y.Equals(nextpos.y)) next = true;
}
}
well, the recommended way is using this simple script
using UnityEngine;
public class Rotating : MonoBehaviour
{
public float speed;
public GameObject pipe;
float r, angle;
Vector3 startpos;
private void Start()
{
r = Mathf.Abs(transform.position.y - pipe.transform.position.y);
angle = 0;
transform.position = pipe.transform.position;
startpos = transform.position;
}
void Update()
{
angle = angle + speed * Time.deltaTime;
transform.rotation = Quaternion.EulerAngles(0,0, angle);
transform.position = startpos + (transform.rotation * new Vector3(r, 0, 0));
}
}
I think Quaternion * Vector3 is what you are looking for. Luckily the box's rotation in its own local coordinates is the same rotation you need to apply to the box's position.
public float speed; //how fast to rotate
public float radius; //radius of the cylinder
public float angle; //angle around it
void Update()
{
if (Input.GetKey(KeyCode.LeftArrow))
{
angle = angle + speed * Time.deltaTime;
}
if (Input.GetKey(KeyCode.RightArrow))
{
angle = angle - speed * Time.deltaTime;
}
//figure out the rotation (from euler angles i guess??)
var quat = Quaternion.EulerAngles(new Vector3(0, angle, 0));
//ok uh what is the box position?? lets just multiply
var unrotated_position = new Vector3(radius, 0, 0);
var rotated_position = quat * unrotated_position;
this.transform.position = rotated_position;
//oh yea and also rotate the box in its own local coordinates
this.transform.rotation = quat;
}

Find waypoints along arcing path between two points with customizable apex height & distance

I have a functioning script that creates an arc of waypoints for a cinemachine track between 2 gameobject(vector3's), I'd like to add a variable so that I can control the height of the arc as seen in this pic:
At the moment the method I have creates the arc based on a radius of the distance between the 2 points, I'd like to be able to control the height of the arc so that it calculates the points similar to the drawn line in the pic. And to control where in the arc that maximum height occurs in relationship to the distance between posA and posB.
Here's the code I have for creating the arc as it is at the moment, which calculates the arc with a radius of half the distance between the 2 points:
static void CalcWaypoints(CinemachineSmoothPath path, Vector3 posA, Vector3 posB)
{
int greenRingPointsNum = 8;
float metersPerWaypoint = 10;
//Here we calculate how many segments will fit between the two points
int segmentsToCreate = Mathf.RoundToInt(Vector3.Distance(posA, posB) / metersPerWaypoint);
path.m_Waypoints = new CinemachineSmoothPath.Waypoint[segmentsToCreate + greenRingPointsNum];
Debug.Log("Creating " + segmentsToCreate + " waypoints");
// get circle center and radius
var radius = Vector3.Distance(posA, posB) / 2f;
var centerPos = (posA + posB) / 2f;
// get a rotation that looks in the direction of the target gameobject
var centerDirection = Quaternion.LookRotation((posA - posB).normalized);
for (var i = 0; i < segmentsToCreate; i++)
{
var angle = Mathf.PI * (i) / (segmentsToCreate + 1f);
var y = Mathf.Sin(angle) * radius;
var z = Mathf.Cos(angle) * radius;
var pos = new Vector3(0, y, z);
// Rotate the pos vector according to the centerDirection
pos = centerDirection * pos;
path.m_Waypoints[i] = new CinemachineSmoothPath.Waypoint();
path.m_Waypoints[i].position = centerPos + pos;
}
//create a circle of points around the target gameobject at a give radius
float greenRadius = 20f;
int waypointNum = segmentsToCreate;
for (int i = 0; i < greenRingPointsNum; i++)
{
float angle = i * Mathf.PI * 2f / greenRingPointsNum;
Vector3 newPos = posB + new Vector3(Mathf.Cos(angle) * greenRadius, posB.y, Mathf.Sin(angle) * greenRadius);
path.m_Waypoints[waypointNum] = new CinemachineSmoothPath.Waypoint();
path.m_Waypoints[waypointNum].position = newPos;
waypointNum++;
}
}
Hope one of you great folks can help out :)
An Arc like the following pic, where I can control the height and it's distance between the 2 points:
The easiest way to do this would probably be by dynamically making Bézier curves and then following them.
First, we define what direction the apex should be in, and find the apex:
float apexHeightFromA = 5f; // apex is 5 world units above A
float apexDistanceFactor = 0.5f; // apex is halfway from A to B
Vector3 upDirection = Vector3.up; // direction apex is in relative to points
Vector3 aToB = posB - posA;
Vector3 flatAToB = Vector3.ProjectOnPlane(aToB, upDirection);
Vector3 posApex = posA
+ flatAToB * apexDistanceFactor
+ apexHeightFromA * upDirection;
Now, the Bézier curves can be defined. If we use two cubic Bézier curves, we will need two control points, one on either side of the apex. That is to say, one going toward point A and one going toward point B.
Vector3 controlPointApexA;
Vector3 controlPointApexB;
It's arbitrary how to define these. A good starting point might be going horizontally halfway to the end each control point is towards.
Vector3 apexToA = posA - posApex;
Vector3 apexToB = posB - posApex;
float controlPointDistanceFactor = 0.5f;
controlPointA = posApex
+ controlPointDistanceFactor * Vector3.ProjectOnPlane(apexToA, upDirection);
controlPointB = posApex
+ controlPointDistanceFactor * Vector3.ProjectOnPlane(apexToB, upDirection);
However we define the control points, we can proceed with the iteration along the curve.
First, we need to determine how many waypoints should come before vs after the apex. A reasonable assumption is for it to be reached according to its position between the points.
float apexTravelFactor = apexDistanceFactor;
Then, we can use the formula for a quadratic Bézier curve...
... from A to apex or from apex to B depending on where we are in the curve.:
// cache for efficiency
Vector3 controlAToA = posA - controlPointA;
Vector3 controlBToB = posB - controlPointB;
Vector3 controlAToApex = posApex - controlPointA;
Vector3 controlBToApex = posApex - controlPointB;
for (var i = 0; i < segmentsToCreate; i++)
{
float overallT = (float)i / segmentsToCreate;
Vector3 control, controlToOrigin, controlToDest;
float t;
// are we going from a to apex or apex to b?
if (overallT < apexTravelFactor)
{
// going from a to apex
control = controlPointA;
controlToOrigin = controlAToA;
controlToDest = controlAToApex;
t = overallT / apexTravelFactor;
}
else
{
// going from apex to b
control = controlPointB;
controlToOrigin = controlBToApex;
controlToDest = controlBToB;
t = (overallT - apexTravelFactor) / (1f - apexTravelFactor);
}
Vector3 currentPos = control
+ Mathf.Pow(1f - t, 2f) * controlToOrigin
+ Mathf.Pow(t, 2f) * controlToDest;
path.m_Waypoints[i] = new CinemachineSmoothPath.Waypoint();
path.m_Waypoints[i].position = currentPos;
}
Altogether, moving constants & such to the top:
static void CalcWaypoints(CinemachineSmoothPath path, Vector3 posA, Vector3 posB)
{
//////////////////////////////////////////////
// CONSTANTS & FACTORS
// good candidates for [Serializable] fields
// in a singleton and/or if this were not static
//////////////////////////////////////////////
int greenRingPointsNum = 8;
float metersPerWaypoint = 10;
float apexHeightFromA = 5f; // apex is 5 world units above A
float apexDistanceFactor = 0.5f; // apex is halfway from A to B
Vector3 upDirection = Vector3.up; // direction apex is in relative to points
// can fiddle with to change "thickness" of curve
float controlPointDistanceFactor = 0.5f;
// can fiddle with to change how many waypoints come before vs after the apex
float apexTravelFactor = apexDistanceFactor;
////////
// LOGIC
////////
Vector3 aToB = posB - posA;
//Here we calculate how many segments will fit between the two points
int segmentsToCreate = Mathf.RoundToInt(aToB.magnitude / metersPerWaypoint);
path.m_Waypoints = new CinemachineSmoothPath.Waypoint[segmentsToCreate
+ greenRingPointsNum];
Debug.Log("Creating " + segmentsToCreate + " waypoints");
Vector3 flatAToB = Vector3.ProjectOnPlane(aToB, upDirection);
Vector3 posApex = posA
+ flatAToB * apexDistanceFactor
+ apexHeightFromA * upDirection;
Vector3 apexToA = posA - posApex;
Vector3 apexToB = posB - posApex;
Vector3 controlPointA = posApex
+ controlPointDistanceFactor
* Vector3.ProjectOnPlane(apexToA, upDirection);
Vector3 controlPointB = posApex
+ controlPointDistanceFactor
* Vector3.ProjectOnPlane(apexToB, upDirection);
Vector3 controlAToA = posA - controlPointA;
Vector3 controlBToB = posB - controlPointB;
Vector3 controlAToApex = posApex - controlPointA;
Vector3 controlBToApex = posApex - controlPointB;
for (var i = 0; i < segmentsToCreate; i++)
{
float overallT = (float)i / segmentsToCreate;
// if you want to have waypoint at posB:
// float overallT = (float)i / (segmentsToCreate-1);
Vector3 control, controlToOrigin, controlToDest;
float t;
// are we going from a to apex or apex to b?
if (overallT < apexTravelFactor)
{
// going from a to apex
control = controlPointA;
controlToOrigin = controlAToA;
controlToDest = controlAToApex;
t = overallT / apexTravelFactor;
}
else
{
// going from apex to b
control = controlPointB;
controlToOrigin = controlBToApex;
controlToDest = controlBToB;
t = (overallT - apexTravelFactor) / (1f - apexTravelFactor);
}
Vector3 currentPos = control
+ Mathf.Pow(1f - t, 2f) * controlToOrigin
+ Mathf.Pow(t, 2f) * controlToDest;
path.m_Waypoints[i] = new CinemachineSmoothPath.Waypoint();
path.m_Waypoints[i].position = currentPos;
}
//create a circle of points around the target gameobject at a give radius
float greenRadius = 20f;
int waypointNum = segmentsToCreate;
for (int i = 0; i < greenRingPointsNum; i++)
{
float angle = i * Mathf.PI * 2f / greenRingPointsNum;
Vector3 newPos = posB + new Vector3(Mathf.Cos(angle) * greenRadius, posB.y,
Mathf.Sin(angle) * greenRadius);
path.m_Waypoints[waypointNum] = new CinemachineSmoothPath.Waypoint();
path.m_Waypoints[waypointNum].position = newPos;
waypointNum++;
}
}
For funzies, try setting a negative value for apexHeightFromA, and/or a value that would put the "apex" between the "heights" of posA and posB. You'll see that it should still look ok, although it certainly won't be an "apex" anymore ;)
If you want to preview the waypoints, see below:
public class TestScript : MonoBehaviour
{
[SerializeField]
float apexHeightFromA = 5f; // apex is 5 world units above A
[SerializeField] float apexDistanceFactor = 0.5f; // apex is halfway from A to B
[SerializeField] Vector3 upDirection = Vector3.up; // direction apex is in relative to points
[SerializeField] Vector3 posA;
[SerializeField] Vector3 posB;
private void OnDrawGizmos()
{
CalcWaypoints();
}
void CalcWaypoints()
{
//////////////////////////////////////////////
// CONSTANTS & FACTORS
// good candidates for [Serializable] fields
// in a singleton and/or if this were not static
//////////////////////////////////////////////
// animate apex distance factor
apexDistanceFactor = Mathf.PingPong(Time.time * 0.3f, .8f) + 0.1f;
float metersPerWaypoint = 10;
// can fiddle with to change "thickness" of curve
float controlPointDistanceFactor = 0.5f;
// can fiddle with to change how many waypoints come before vs after the apex
float apexTravelFactor = apexDistanceFactor;
////////
// LOGIC
////////
Vector3 aToB = posB - posA;
//Here we calculate how many segments will fit between the two points
int segmentsToCreate = Mathf.RoundToInt(aToB.magnitude / metersPerWaypoint);
Debug.Log("Creating " + segmentsToCreate + " waypoints");
Vector3 flatAToB = Vector3.ProjectOnPlane(aToB, upDirection);
Vector3 posApex = posA
+ flatAToB * apexDistanceFactor
+ apexHeightFromA * upDirection;
Vector3 apexToA = posA - posApex;
Vector3 apexToB = posB - posApex;
Vector3 controlPointA = posApex
+ controlPointDistanceFactor
* Vector3.ProjectOnPlane(apexToA, upDirection);
Vector3 controlPointB = posApex
+ controlPointDistanceFactor
* Vector3.ProjectOnPlane(apexToB, upDirection);
Vector3 controlAToA = posA - controlPointA;
Vector3 controlBToB = posB - controlPointB;
Vector3 controlAToApex = posApex - controlPointA;
Vector3 controlBToApex = posApex - controlPointB;
for (var i = 0; i < segmentsToCreate; i++)
{
float overallT = (float)i / (segmentsToCreate + 1);
// if you want to have waypoint at posB:
// float overallT = (float)i / (segmentsToCreate-1);
Vector3 control, controlToOrigin, controlToDest;
float t;
// are we going from a to apex or apex to b?
if (overallT < apexTravelFactor)
{
// going from a to apex
control = controlPointA;
controlToOrigin = controlAToA;
controlToDest = controlAToApex;
t = overallT / apexTravelFactor;
}
else
{
// going from apex to b
control = controlPointB;
controlToOrigin = controlBToApex;
controlToDest = controlBToB;
t = (overallT - apexTravelFactor) / (1f - apexTravelFactor);
}
Vector3 currentPos = control
+ Mathf.Pow(1f - t, 2f) * controlToOrigin
+ Mathf.Pow(t, 2f) * controlToDest;
Gizmos.DrawSphere(currentPos, 1f);
}
}
}

Cast x number of rays in all direction in Unity

I am trying to cast x(500) rays in a circular direction(360) in unity. so that 500 rays get cast on equidistance to form a complete circle. I tried something but it leaves out some area I don't know why. how do I make it full circle?
my code
float number_of_rays = 500;
float angle = 360 / number_of_rays;
float cast_angle = 0;
for (int i = 0; i < number_of_rays; i++)
{
var dir = Quaternion.Euler(0, 0, cast_angle) * transform.right;
RaycastHit2D hit = Physics2D.Raycast(transform.position, dir, Mathf.Infinity);
if (hit)
{
points.Add(hit.point);
Debug.DrawLine(transform.position, hit.point, Color.green,1f);
}
cast_angle += angle;
}
Consider that maybe it just doesn't find a raycast hit in the space you don't get your rays drawn.
This code seems to work for me.
float number_of_rays = 500;
float totalAngle = 360;
float delta = totalAngle / number_of_rays;
Vector3 pos = transform.position;
const float magnitude = 5;
for (int i = 0; i < number_of_rays; i++)
{
var dir = Quaternion.Euler(0, 0, i * delta) * transform.right;
Debug.DrawRay(pos, dir * magnitude, Color.green);
}

How do I make a pool cue rotate around the cue ball?

I want the pool cue to rotate around the cue ball as the player drags the mouse, I've played some pool games on the internet and they all seem to work this way. This will eventually be a browser game.
This game isn't mine, but it has the basic mechanic that I want (I don't care about the lines that are displayed, I just want the rotate and hit mechanic) https://www.crazygames.com/game/8-ball-billiards-classic
I have tried some orbiting scripts so far, none of them work.
I've tried some scripts that make objects orbit based on time hoping to make it so it orbits with the mouse dragging instead of time. I also can't get the cue to constantly face the cue ball.
This code has gotten me the closest.
public int vertexCount = 40;
public float lineWidth = 0.2f;
public float radius;
public bool circleFillscreen;
//circle variables
static float timeCounter = 0;
float width;
float height;
private LineRenderer lineRenderer;
private void Awake()
{
lineRenderer = GetComponent<LineRenderer>();
SetupCircle();
}
void Update()
{
timeCounter += Time.deltaTime;
float x = Mathf.Cos(timeCounter);
float y = 0;
float z = Mathf.Sin(timeCounter);
}
private void SetupCircle()
{
lineRenderer.widthMultiplier = lineWidth;
if (circleFillscreen)
{
radius = Vector3.Distance(Camera.main.ScreenToWorldPoint(new Vector3(0f, Camera.main.pixelRect.yMax, 0f)),
Camera.main.ScreenToWorldPoint(new Vector3(0f, Camera.main.pixelRect.yMin, 0f))) * 0.5f - lineWidth;
}
float deltaTheta = (2f * Mathf.PI) / vertexCount;
float theta = 0F;
lineRenderer.positionCount = -vertexCount;
for (int i = 0; i < lineRenderer.positionCount; i++)
{
Vector3 pos = new Vector3(radius * Mathf.Cos(theta), radius * Mathf.Sin(theta), 0f);
lineRenderer.SetPosition(i, pos);
theta += deltaTheta;
}
}
#if UNITY_EDITOR
private void OnDrawGizmos()
{
float deltaTheta = (2f * Mathf.PI) / vertexCount;
float theta = 0f;
Vector3 oldPos = Vector3.zero;
for (int i = 0; i < vertexCount + 1; i++)
{
Vector3 pos = new Vector3(radius * Mathf.Cos(theta), 0F,radius * Mathf.Sin(theta));
Gizmos.DrawLine(oldPos, transform.position + pos);
oldPos = transform.position + pos;
theta += deltaTheta;
}
}
#endif
}
Not really getting any error messages, code "works" but doesn't work.

Moving the character controller to vector 3 position

I'm currently making my Boss AI perform a jump attack against the player, the AI use both navmesh and character controller for movment (navmash only for pathfinding), but I'm having a hard time trying to move the AI to the designated position. here is my code:
CharacterController chara;
[SerializeField]
Transform playerTran;
[SerializeField]
float gravity = 3.8f;
[SerializeField]
float jumpForce = 50F;
Vector3 moveVector = Vector3.zero;
[SerializeField]
Transform jumpCheck;
[SerializeField]
Transform jumpPos;
// Use this for initialization
void Start ()
{
chara = GetComponent<CharacterController>();
playerTran = GameObject.FindGameObjectWithTag("Player").GetComponent<Transform>();
}
// Update is called once per frame
void Update ()
{
chara.Move(moveVector);
if (chara.isGrounded)
{
transform.LookAt(playerTran);
}
moveVector -= Vector3.up * gravity * Time.deltaTime;
if (Input.GetKeyUp(KeyCode.J))
{
jumpCheck.position = new Vector3(playerTran.position.x, 0, playerTran.position.z);
float angle = findAngle( playerTran.position.x - transform.position.x , playerTran.position.z - transform.position.z);
Vector3 _toJumpPos = MakeJumpCricle(playerTran.position , jumpCheck.localScale.x/2, angle);
jumpPos.position = new Vector3(_toJumpPos.x, 0, _toJumpPos.z);
moveVector = Vector3.up * jumpForce * Time.deltaTime;
}
}
float findAngle(float x, float y)
{
float value;
value = (float)((Mathf.Atan2(x, y) / Mathf.PI) * 180);
if (value < 0)
{
value += 360;
}
Debug.Log(value);
return value;
}
Vector3 MakeJumpCricle( Vector3 center, float radius, float angle)
{
Vector3 pos = Vector3.zero;
pos.x = center.x - radius * Mathf.Sin(angle * Mathf.Deg2Rad);
pos.y = 0;
pos.z = center.z - radius * Mathf.Cos(angle * Mathf.Deg2Rad);
return pos;
}
I want to move the AI to the jumpPos with both forward and up vectors but I'm not sure to do this.
visualization of the code
code visualization
I found a good solution, I used a Bezier Curves to generate a path
posting it here so other might find it helpful.
refrence link
http://www.theappguruz.com/blog/bezier-curve-in-games
public LineRenderer jumpLine;
private int numberOfPoint = 50;
[SerializeField]
List<Vector3> pointPositions = new List<Vector3>();
CharacterController chara;
[SerializeField]
Transform playerTran;
[SerializeField]
float gravity = 3.8f;
[SerializeField]
float jumpForce = 50F;
Vector3 moveVector = Vector3.zero;
[SerializeField]
Transform jumpCheck;
[SerializeField]
Transform jumpPos;
[SerializeField]
Transform jumpHightOne;
bool movejump;
Vector3 pZero;
Vector3 pOne;
float time;
// Use this for initialization
void Start ()
{
chara = GetComponent<CharacterController>();
playerTran = GameObject.FindGameObjectWithTag("Player").GetComponent<Transform>();
jumpLine.positionCount = numberOfPoint;
jumpLine.gameObject.SetActive(false);
}
// Update is called once per frame
void Update ()
{
chara.Move(moveVector);
if (chara.isGrounded)
{
transform.LookAt(playerTran);
}
moveVector -= Vector3.up * gravity * Time.deltaTime;
if (Input.GetKeyUp(KeyCode.J))
{
jumpCheck.position = new Vector3(playerTran.position.x, 0, playerTran.position.z);
float angle = findAngle( playerTran.position.x - transform.position.x , playerTran.position.z - transform.position.z);
Vector3 _toJumpPos = MakeJumpCricle(playerTran.position , jumpCheck.localScale.x/2, angle);
Vector3 middlePoint = GetTheMiddlePoints(transform.position, playerTran.position, 0.5f);
jumpHightOne.position = new Vector3(middlePoint.x, jumpHightOne.position.y, middlePoint.z);
jumpPos.position = new Vector3(_toJumpPos.x, 0, _toJumpPos.z);
//moveVector = Vector3.up * jumpForce * Time.deltaTime;
//movejump = true;
DrawLinerBezierCurves();
}
if (movejump)
{
//MoveTowardsTarget(jumpPos.position);
}
}
Vector3 GetTheMiddlePoints(Vector3 origin, Vector3 destination, float middlepointfactor)
{
return (destination - origin) * middlepointfactor + origin;
// (destination - origin) * 0.5f;
}
float findAngle(float x, float y)
{
float value;
value = (float)((Mathf.Atan2(x, y) / Mathf.PI) * 180);
if (value < 0)
{
value += 360;
}
//Debug.Log(value);
return value;
}
Vector3 MakeJumpCricle( Vector3 center, float radius, float angle)
{
Vector3 pos = Vector3.zero;
pos.x = center.x - radius * Mathf.Sin(angle * Mathf.Deg2Rad);
pos.y = 0;
pos.z = center.z - radius * Mathf.Cos(angle * Mathf.Deg2Rad);
return pos;
}
void MoveTowardsTarget(Vector3 targetPostios)
{
var offset = targetPostios - transform.position;
if (offset.magnitude > .1f)
{
offset = offset.normalized * 15;
chara.Move(offset * Time.deltaTime);
}
else
{
movejump = false;
}
}
// line Bezier Curves
Vector3 CalculateBezierCurvesPoints(float t , Vector3 p0, Vector3 p1 )
{
return p0 + t * (p1 - p0);
// P = P0 + t(P1 – P0) , 0 < t < 1
}
// line Bezier Curves
Vector3 CalculateBezierCurvesPoints(float t, Vector3 p0, Vector3 p1, Vector3 p2)
{
float u = 1 - t;
float uu = u * u;
float tt = t * t;
Vector3 p = uu * p0;
p = p + 2 * u * t * p1;
p = p + tt * p2;
return p;
//P = (1-t)^2 P0 + 2 (1-t) t P1 + t^2 P2 , 0 < t < 1
// uu u tt
// uu * p0 + 2 * u * t * p1 + tt * p2
}
void DrawLinerBezierCurves()
{
if (pointPositions.Count > 0)
{
pointPositions.Clear();
jumpLine.positionCount = 0;
jumpLine.positionCount = numberOfPoint;
}
for (int i = 1; i < numberOfPoint + 1; i++)
{
float t = i / (float) numberOfPoint;
if (!jumpLine.gameObject.activeInHierarchy)
{
jumpLine.gameObject.SetActive(true);
}
pointPositions.Add(CalculateBezierCurvesPoints(t, transform.position,jumpHightOne.position, jumpPos.position));
jumpLine.SetPosition(i - 1, pointPositions[i - 1]);
}
}

Categories