So I have made a Trajectory for my ball.
This is the code...
{
[Header("Line renderer veriables")]
public LineRenderer line;
[Range(2, 30)]
public int resolution;
Rigidbody rb;
[Header("Formula variables")]
public Vector3 velocity;
public float yLimit;
private float g;
[Header("Linecast variables")]
[Range(2, 30)]
public int linecastResolution;
public LayerMask canHit;
public Rigidbody ballRigid;
private void Start()
{
rb = GetComponent<Rigidbody>();
g = Mathf.Abs(Physics.gravity.y);
}
private void Update()
{
RenderArc();
}
private void RenderArc()
{
line.positionCount = resolution + 1;
line.SetPositions(CalculateLineArray());
}
private Vector3[] CalculateLineArray()
{
Vector3[] lineArray = new Vector3[resolution + 1];
var lowestTimeValueX = MaxTimeX() / resolution;
var lowestTimeValueZ = MaxTimeZ() / resolution;
var lowestTimeValue = lowestTimeValueX > lowestTimeValueZ ? lowestTimeValueZ : lowestTimeValueX;
for (int i = 0; i < lineArray.Length; i++)
{
var t = lowestTimeValue * i;
lineArray[i] = CalculateLinePoint(t);
}
return lineArray;
}
private Vector3 HitPosition()
{
var lowestTimeValue = MaxTimeY() / linecastResolution;
for (int i = 0; i < linecastResolution + 1; i++)
{
RaycastHit rayHit;
var t = lowestTimeValue * i;
var tt = lowestTimeValue * (i + 1);
if (Physics.Linecast(CalculateLinePoint(t), CalculateLinePoint(tt), out rayHit, canHit))
return rayHit.point;
}
return CalculateLinePoint(MaxTimeY());
}
private Vector3 CalculateLinePoint(float t)
{
float x = rb.velocity.x * t;
float z = rb.velocity.z * t;
float y = (rb.velocity.y * t) - (g * Mathf.Pow(t, 2) / 2);
return new Vector3(x + transform.position.x, y + transform.position.y, z + transform.position.z);
}
private float MaxTimeY()
{
var v = rb.velocity.y;
var vv = v * v;
var t = (v + Mathf.Sqrt(vv + 2 * g * (transform.position.y - yLimit))) / g;
return t;
}
private float MaxTimeX()
{
if (IsValueAlmostZero(velocity.x))
SetValueToAlmostZero(ref velocity.x);
var x = rb.velocity.x;
var t = (HitPosition().x - transform.position.x) / x;
return t;
}
private float MaxTimeZ()
{
if (IsValueAlmostZero(velocity.z))
SetValueToAlmostZero(ref velocity.z);
var z = rb.velocity.z;
var t = (HitPosition().z - transform.position.z) / z;
return t;
}
private bool IsValueAlmostZero(float value)
{
return value < 0.0001f && value > -0.0001f;
}
private void SetValueToAlmostZero(ref float value)
{
value = 0.0001f;
}
public void SetVelocity(Vector3 velocity)
{
this.velocity = velocity;
}
}
I have a slingshot With a objectholder(which holds the ball). Also I have a robot arm that pulls the objectholder with its clawhand . The arm pulls it but The ball is in kinematic until the claw opens. The objectholder contains springs joints so its able to go back to its place and make a elastic effect and throw the ball. Now with this code when I pull the trajectory doesnt appear until i let go and it picks a target by itself and just follows the line. What i want is when I pull it the trajectory shows and the user is able to pick the target or move the trajectory. Note: (If i get rid of rb.velocity and replace it with velocity, then when i pull it it shows the trajectory and I can change the target but when i open my claw and the ball shoots, it doesnt follow the trajectory, its like the trajectory follows the ball. Can someone helps? This code makes the ball follows the line so its good I just have that problem.
My other code when clawhand opens and closes and ball is kinematic or not:
public class open2close : MonoBehaviour
{
public float speed;
private Animation anim;
[SerializeField] bool isClosed;
private bool isKinematic;
public Transform rightClaw;
public Vector3 offset;
public Rigidbody Rb2;
public Rigidbody ball_Rigid;
void Start()
{ Debug.Log(transform.position);
Console.WriteLine("test");
anim = gameObject.GetComponent<Animation>();
Rb2 = Rb2.GetComponent<Rigidbody>();
ball_Rigid = ball_Rigid.GetComponent<Rigidbody>();
//Rb2.isKinematic = true;
}
void Update()
{
// Debug.Log(transform.position);
if (Input.GetKey(KeyCode.X))
{
anim.Play("clawopen");
isClosed = false;
Rb2.isKinematic = false;
ball_Rigid.isKinematic = false;
}
if (Input.GetKey(KeyCode.Y))
{
anim.Play("clawclose");
isClosed = true;
Rb2.isKinematic = true;
ball_Rigid.isKinematic = true;
}
}
private void OnTriggerStay(Collider spring2)
{
Rigidbody colRb = spring2.attachedRigidbody;
if (isClosed && spring2.transform.gameObject.tag == "Player")
{
spring2.transform.position = rightClaw.transform.position + offset;
}
}
private void OnTriggerExit(Collider spring2)
{
Rigidbody colRb = spring2.attachedRigidbody;
if (isClosed && spring2.transform.gameObject.tag == "Player")
{
colRb.WakeUp();
}
}
}
Im trying to implement a small car system that is somewhat accuarate to real physics. I fount this guide this tutorial Based on which i have tried to make my system.
Im still working on forward movement and aving trouble with acceleration. At full throttle Drive torque and traction torque become equal and no more acceleration is applied to the wheels, and car acceleration stops. But when i look at the RPM calculations, im doing something like 1200 RPM in first gear, and i have 6 gears. Im sure i have made some mistake somewhere, but i cant figure out where. Added my code and component values below. Only rear axle applies force, front axle is free rolling. On gear rations Element 0 is meant to be reverse gear. Can you help me find my mistake?
using UnityEngine;
[System.Serializable]
public class EngineInfo
{
public AnimationCurve torqueCurve;
public float maxTorque;
public float minTorque;
public float maxRPM;
public float minRPM;
public float getEngineTorque(float RPM)
{
float t = (0.05f - 0) / (maxRPM - minRPM) * (RPM - minRPM) + 0;
float val = torqueCurve.Evaluate(t);
return (maxTorque - minTorque) / (0.05f - 0) * (val - 0) + minTorque;
}
}
[System.Serializable]
public class GearboxInfo
{
public float differentialRatio;
public float transmissionEfficiency;
public float[] gearRatios;
public int currentGear = 1;
public EngineInfo engineInfo;
public float RPM = 0;
public float getEngineRPM(float wheelAngularVelocity)
{
return Mathf.Min(Mathf.Max(wheelAngularVelocity * gearRatios[currentGear] * differentialRatio * 60 / (2 * Mathf.PI), engineInfo.minRPM), engineInfo.maxRPM);
}
public float getDriveTorque(float engineTorque)
{
return engineTorque * gearRatios[currentGear] * differentialRatio * transmissionEfficiency;
}
public float getDriveTorque(float throttle, float wheelAngularVelocity)
{
RPM = getEngineRPM(wheelAngularVelocity);
if(RPM / engineInfo.maxRPM > 0.9f)
{
currentGear = Mathf.Min(currentGear + 1, gearRatios.Length - 1);
RPM = getEngineRPM(wheelAngularVelocity);
Debug.Log(currentGear);
}
float engineTorque = throttle * engineInfo.getEngineTorque(RPM);
return getDriveTorque(engineTorque);
}
}
public class PhysicalCarController : MonoBehaviour
{
Rigidbody rb;
private float stationaryWeightTransferConstantFront = 0;
private float stationaryWeightTransferConstantRear = 0;
private float weightTransferConstant = 0;
private float rollingResistanceConstant = 0;
public EngineInfo engineInfo;
public GearboxInfo gearboxInfo;
public WheelAxle rearAxle;
public WheelAxle frontAxle;
public float tireFrictionCoeficcent = 0;
public float frictionCoefficent = 0;
public float areaOfCarFront = 0;
public float airDensity = 0;
public float breakTorque = 0;
public float rrCoefficent = 0;
// Start is called before the first frame update
private float dragConstant = 0;
void Start()
{
rb = GetComponent<Rigidbody>();
float weight = rb.mass * Physics.gravity.magnitude;
Vector3 rearLength = rb.centerOfMass - rearAxle.transform.position;
rearLength.y = 0;
Vector3 frontLength = rb.centerOfMass - frontAxle.transform.position;
frontLength.y = 0;
float c = frontLength.magnitude;
float b = rearLength.magnitude;
float h = 0.46f;
float L = c + b;
stationaryWeightTransferConstantFront = tireFrictionCoeficcent * (c / L) * weight;
stationaryWeightTransferConstantRear = tireFrictionCoeficcent * (b / L) * weight;
weightTransferConstant = (h / L) * rb.mass;
rollingResistanceConstant = rrCoefficent * rb.mass;
dragConstant = 0.5f * frictionCoefficent * areaOfCarFront * airDensity;
gearboxInfo.engineInfo = engineInfo;
}
// Update is called once per frame
void Update()
{
}
private Vector3 last_velocity = Vector3.zero;
public float driveTorque = 0;
private void FixedUpdate()
{
updateWeightTransfer();
updateWheel();
updateEngine();
calculateResistanceForce();
rearAxle.dragForce = totalForce;
}
private float frontLoad = 0;
private float rearLoad = 0;
private void updateWeightTransfer()
{
Vector3 velocity = rb.velocity;
velocity.y = 0;
Vector3 acceleration = (velocity - last_velocity) / Time.fixedDeltaTime;
last_velocity = velocity;
float accelerationMagnitude = acceleration.magnitude;
float dynamicWeightTransfer = weightTransferConstant * accelerationMagnitude;
frontLoad = stationaryWeightTransferConstantFront - dynamicWeightTransfer;
rearLoad = stationaryWeightTransferConstantRear + dynamicWeightTransfer;
}
private void updateWheel()
{
rearAxle.axleLoad = rearLoad;
rearAxle.driveTorque = driveTorque;
rearAxle.breakTorque = 0;
frontAxle.axleLoad = frontLoad;
}
private void updateEngine()
{
float throttle = Input.GetAxis("Vertical");
driveTorque = gearboxInfo.getDriveTorque(throttle, rearAxle.getWheelAngularVelocity());
}
private Vector3 totalForce = Vector3.zero;
private void calculateResistanceForce()
{
if (rb.velocity.magnitude > 0)
{
float speed = Mathf.Sign(Vector3.Dot(rb.transform.forward, rb.velocity)) * rb.velocity.magnitude;
if (speed < 0.001f)
{
totalForce = Vector3.zero;
}
else
{
totalForce = -dragConstant * rb.velocity.normalized; // air drag
totalForce += -rollingResistanceConstant * rb.velocity; // rolling resistance
}
}
}
}
using UnityEngine;
[System.Serializable]
public class WheelInfo
{
public float wheelRadius;
public float wheelMass;
public float angularVelocity;
public AnimationCurve slipRatioCurve;
public float curveAtLoad;
public float maxForce;
public float minForce;
public float maxSlip;
public float minSlip;
public float getTractionForce(float slip, float load)
{
float t = (1 - 0) / (maxSlip - minSlip) * (slip - minSlip) + 0;
float val = slipRatioCurve.Evaluate(t);
return ((maxForce - minForce) / (1 - 0) * (val - 0) + minForce) / curveAtLoad * load;
}
}
public class WheelAxle : MonoBehaviour
{
public Vector3 dragForce = Vector3.zero;
public float driveTorque = 0;
public float breakTorque = 0;
public float axleLoad = 0;
public float tractionTorque = 0;
public float slipRatio = 0;
public bool motor = false;
public WheelInfo wheelInfo;
public float inertia;
public Rigidbody rb;
// Start is called before the first frame update
void Start()
{
inertia = wheelInfo.wheelMass * wheelInfo.wheelRadius * wheelInfo.wheelRadius;
}
// Update is called once per frame
void Update()
{
}
private void FixedUpdate()
{
if (motor)
{
Vector3 velocity = rb.velocity;
velocity.y = 0;
float speed = Mathf.Sign(Vector3.Dot(rb.transform.forward, velocity)) * velocity.magnitude;
float slipRatioConstant = wheelInfo.angularVelocity * wheelInfo.wheelRadius;
slipRatio = 0;
if (speed < 0.001f)
{
slipRatio = (slipRatioConstant < 0.0001f) ? 0 : slipRatioConstant - speed / slipRatioConstant;
}
else
{
slipRatio = slipRatioConstant - speed / Mathf.Abs(speed);
}
float totalDrag = Mathf.Sign(Vector3.Dot(rb.transform.forward, dragForce)) * dragForce.magnitude;
float tractionForce = wheelInfo.getTractionForce(slipRatio, axleLoad);
Vector3 directionalTractionForce = Vector3.forward * (tractionForce );
tractionTorque = tractionForce * wheelInfo.wheelRadius;
float totalTorque = driveTorque + Mathf.Sign(driveTorque) * (tractionTorque + breakTorque) * -1;
float angularAcceleration = totalTorque / inertia;
wheelInfo.angularVelocity += angularAcceleration * Time.fixedDeltaTime;
if (wheelInfo.angularVelocity < 0.001f)
{
wheelInfo.angularVelocity = 0;
}
rb.AddForceAtPosition(directionalTractionForce * 2 + dragForce, transform.position);
}
}
public float getWheelAngularVelocity()
{
return wheelInfo.angularVelocity;
}
}
EDIT:
After playing around with some numbers and trying to find some real world values i was able to get the car moving. I still have 1 mystery left.
rb.AddForceAtPosition(directionalTractionForce * 2 + dragForce, transform.position);
The directionalTractionForce should be per wheel, and since i have 2 drive wheels hence the *2 But this was not able to move the car. But if i set it to *4 then everything works fine. Can someone explain me why is it *4 and not *2 if the directionalTractionForce is per wheel? Where have a made a miscalculation.
I am trying to develop a loop menu through Scrollrect, and I want to make it as the picture to the menu, how should I do??
For this effect, I have two questions, one is how should I do to make the long distance objects with a smaller scale
the other question is how to adding depth to different button
Here is my code with scrollrect which can loop the button:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using DG;
public class ScrollRectSnap4 : MonoBehaviour {
public RectTransform panel;
public Button[] bttn;
public RectTransform center;
public float[] distance;
public float[] distReposition;
private bool dragging = false;
public int bttnDistance;
private int minButtonNum;
private int bttnLenght;
public float minDistance;
void Start () {
bttnLenght = bttn.Length;
distance = new float[bttnLenght];
distReposition = new float[bttnLenght];
bttnDistance = (int)Mathf.Abs(bttn[1].GetComponent<RectTransform>().anchoredPosition.x - bttn[0].GetComponent<RectTransform>().anchoredPosition.x);
}
void Update () {
for (int i = 0; i < bttn.Length; i++) {
distReposition[i] = center.transform.position.x -
bttn[i].transform.position.x;
distance [i] = Mathf.Abs (distReposition[i]);
if (distReposition [i] > 1200) {
float curX = bttn [i].GetComponent<RectTransform> ().anchoredPosition.x;
float curY = bttn [i].GetComponent<RectTransform> ().anchoredPosition.y;
Vector2 newAnchoredPos1 = new Vector2 (curX + (bttnLenght * bttnDistance), curY);
//Debug.Log (bttn[i].name + "newAnchoredPos1: " + newAnchoredPos1);
bttn [i].GetComponent<RectTransform> ().anchoredPosition = newAnchoredPos1;
}
if (distReposition [i] < -1200) {
float curX = bttn [i].GetComponent<RectTransform> ().anchoredPosition.x;
float curY = bttn [i].GetComponent<RectTransform> ().anchoredPosition.y;
Vector2 newAnchoredPos2 = new Vector2 (curX - (bttnLenght * bttnDistance), curY);
bttn [i].GetComponent<RectTransform> ().anchoredPosition = newAnchoredPos2;
}
}
minDistance = Mathf.Min (distance);
for (int a = 0; a < bttn.Length; a++) {
if (minDistance == distance [a]) {
minButtonNum = a;
bttn[a].transform.localScale = Vector3.Lerp(bttn[a].transform.localScale,new Vector3(1f,1f,1f),Time.deltaTime*5);
} else {
bttn[a].transform.localScale = Vector3.Lerp(bttn[a].transform.localScale,new Vector3(0.7f,0.7f,0.7f),Time.deltaTime*5);
}
}
if (!dragging) {
//LerpToBttn (minButtonNum * -bttnDistance);
LerpToBttn (-bttn[minButtonNum].GetComponent<RectTransform>().anchoredPosition.x);
}
}
void LerpToBttn (float position){
//Debug.Log ("Position: " + -bttn[minButtonNum].GetComponent<RectTransform>().anchoredPosition.x);
float newX = Mathf.Lerp (panel.anchoredPosition.x, position, Time.deltaTime * 5f);
Vector2 newPosition = new Vector2 (newX, panel.anchoredPosition.y);
panel.anchoredPosition = newPosition;
}
public void StartDrag(){
dragging = true;
}
public void EndDrag(){
dragging = false;
}
}
I've some problem when draw manual in unity 2d.
I used list vector to draw polygon, but I can't fill it.
I also read this tutorial: http://forum.unity3d.com/threads/draw-polygon.54092/
But it's seem I need to convert polygon to triangles.(because my polygon is complex so convert to triangles is hard. I need to use some algorithm like Ear clipping...).
Please help me an easy way to fill it. (I think unity is top of game engine, then have some way to do it easiest).
Thanks so so much.
You are stuck with converting to mesh to get fill to work... GPUs(shaders) can only fill the interior spaces of triangles... This is fairly easy if you are working with closed convex polygons. Polygons with concave sections will take a bit more complicated algorithm to convert to mesh, but it seems you've already done some research on the subject (you mentioned ear clipping).
Good luck implementing your polygon list to triangle algo :)
I can offer Poisson-Disc algorithm remodel UniformPoissonDiskSampler.cs like :
using System;
using System.Collections.Generic;
using UnityEngine;
namespace AwesomeNamespace
{
public static class UniformPoissonDiskSampler
{
public const int DefaultPointsPerIteration = 30;
static readonly float SquareRootTwo = (float)Math.Sqrt(2);
struct Settings
{
public UnityEngine.Vector2 TopLeft, LowerRight, Center;
public UnityEngine.Vector2 Dimensions;
public float? RejectionSqDistance;
public float MinimumDistance;
public float CellSize;
public int GridWidth, GridHeight;
}
struct State
{
public UnityEngine.Vector2?[,] Grid;
public List<UnityEngine.Vector2> ActivePoints, Points;
}
public static List<UnityEngine.Vector2> SampleCircle(UnityEngine.Vector2 center, float radius, float minimumDistance)
{
return SampleCircle(center, radius, minimumDistance, DefaultPointsPerIteration);
}
public static List<UnityEngine.Vector2> SampleCircle(UnityEngine.Vector2 center, float radius, float minimumDistance, int pointsPerIteration)
{
return Sample(center - new UnityEngine.Vector2(radius, radius), center + new UnityEngine.Vector2(radius, radius), radius, minimumDistance, pointsPerIteration, null);
}
public static List<UnityEngine.Vector2> SampleRectangle(UnityEngine.Vector2 topLeft, UnityEngine.Vector2 lowerRight, float minimumDistance)
{
return SampleRectangle(topLeft, lowerRight, minimumDistance, DefaultPointsPerIteration);
}
public static List<UnityEngine.Vector2> SampleRectangle(UnityEngine.Vector2 topLeft, UnityEngine.Vector2 lowerRight, float minimumDistance, int pointsPerIteration)
{
return Sample(topLeft, lowerRight, null, minimumDistance, pointsPerIteration, null);
}
public static List<UnityEngine.Vector2> SamplePolygon(UnityEditor.Experimental.TerrainAPI.Processing.InMetric metric, float minimumDistance)
{
return Sample(null, null, null, minimumDistance, DefaultPointsPerIteration, metric);
}
static List<UnityEngine.Vector2> Sample(UnityEngine.Vector2? topLeft, UnityEngine.Vector2? lowerRight, float? rejectionDistance, float minimumDistance, int pointsPerIteration, UnityEditor.Experimental.TerrainAPI.Processing.InMetric metric = null)
{
if (!topLeft.HasValue && !lowerRight.HasValue && metric != null)
{
topLeft = new Vector2(metric.minpointx, metric.minpointz);
lowerRight = new Vector2(metric.maxpointx, metric.maxpointz);
}
var settings = new Settings
{
TopLeft = (Vector2)topLeft,
LowerRight = (Vector2)lowerRight,
Dimensions = (Vector2)lowerRight - (Vector2)topLeft,
Center = ((Vector2)topLeft + (Vector2)lowerRight) / 2,
CellSize = minimumDistance / SquareRootTwo,
MinimumDistance = minimumDistance,
RejectionSqDistance = rejectionDistance == null ? null : rejectionDistance * rejectionDistance
};
settings.GridWidth = (int)(settings.Dimensions.x / settings.CellSize) + 1;
settings.GridHeight = (int)(settings.Dimensions.y / settings.CellSize) + 1;
// Debug.Log("settings.GridWidth"+settings.GridWidth+"settings.GridHeight"+settings.GridHeight);
var state = new State
{
Grid = new UnityEngine.Vector2?[settings.GridWidth, settings.GridHeight],
ActivePoints = new List<UnityEngine.Vector2>(),
Points = new List<UnityEngine.Vector2>()
};
AddFirstPoint(ref settings, ref state, (metric == null) ? null : metric);
while (state.ActivePoints.Count != 0)
{
var listIndex = RandomHelper.Random.Next(state.ActivePoints.Count);
var point = state.ActivePoints[listIndex];
var found = false;
for (var k = 0; k < pointsPerIteration; k++)
found |= AddNextPoint(point, ref settings, ref state, (metric == null) ? null : metric);
if (!found)
state.ActivePoints.RemoveAt(listIndex);
}
return state.Points;
}
static void AddFirstPoint(ref Settings settings,
ref State state,
UnityEditor.Experimental.TerrainAPI.Processing.InMetric metric = null)
{
var added = false;
while (!added)
{
var d = RandomHelper.Random.NextDouble();
var xr = settings.TopLeft.x + settings.Dimensions.x * d;
d = RandomHelper.Random.NextDouble();
var yr = settings.TopLeft.y + settings.Dimensions.y * d;
var p = new UnityEngine.Vector2((float)xr, (float)yr);
if (settings.RejectionSqDistance != null && DistanceSquared(settings.Center, p) > settings.RejectionSqDistance)
continue;
added = true;
if (UnityEditor.Experimental.TerrainAPI.Processing.figures_Included(p.x, p.y, metric.metricIn, metric.count) == true)
{
var index = Denormalize(p, settings.TopLeft, settings.CellSize);
state.Grid[(int)index.x, (int)index.y] = p;
state.ActivePoints.Add(p);
state.Points.Add(p);
}
else
{
AddFirstPoint(ref settings, ref state, metric);
}
}
}
static float DistanceSquared(Vector2 A, Vector2 B)
{
return (float)Math.Pow(Math.Sqrt(Math.Pow((A.x - B.x), 2) + Math.Pow((A.y - B.y), 2)), 2);
}
static bool AddNextPoint(UnityEngine.Vector2 point,
ref Settings settings,
ref State state,
UnityEditor.Experimental.TerrainAPI.Processing.InMetric metric = null)
{
var found = false;
var q = GenerateRandomAround(point, settings.MinimumDistance);
if (metric != null)
{
if (UnityEditor.Experimental.TerrainAPI.Processing.figures_Included(q.x, q.y, metric.metricIn, metric.count) == true &&
q.x >= settings.TopLeft.x && q.x < settings.LowerRight.x &&
q.y > settings.TopLeft.y && q.y < settings.LowerRight.y &&
(settings.RejectionSqDistance == null || DistanceSquared(settings.Center, q) <= settings.RejectionSqDistance))
{
var qIndex = Denormalize(q, settings.TopLeft, settings.CellSize);
var tooClose = false;
for (var i = (int)Math.Max(0, qIndex.x - 2); i < Math.Min(settings.GridWidth, qIndex.x + 3) && !tooClose; i++)
for (var j = (int)Math.Max(0, qIndex.y - 2); j < Math.Min(settings.GridHeight, qIndex.y + 3) && !tooClose; j++)
if (state.Grid[i, j].HasValue && Vector2.Distance(state.Grid[i, j].Value, q) < settings.MinimumDistance)
tooClose = true;
if (!tooClose)
{
found = true;
state.ActivePoints.Add(q);
state.Points.Add(q);
state.Grid[(int)qIndex.x, (int)qIndex.y] = q;
}
}
}
else
{
if (q.x >= settings.TopLeft.x && q.x < settings.LowerRight.x &&
q.y > settings.TopLeft.y && q.y < settings.LowerRight.y &&
(settings.RejectionSqDistance == null || DistanceSquared(settings.Center, q) <= settings.RejectionSqDistance))
{
var qIndex = Denormalize(q, settings.TopLeft, settings.CellSize);
var tooClose = false;
for (var i = (int)Math.Max(0, qIndex.x - 2); i < Math.Min(settings.GridWidth, qIndex.x + 3) && !tooClose; i++)
for (var j = (int)Math.Max(0, qIndex.y - 2); j < Math.Min(settings.GridHeight, qIndex.y + 3) && !tooClose; j++)
if (state.Grid[i, j].HasValue && Vector2.Distance(state.Grid[i, j].Value, q) < settings.MinimumDistance)
tooClose = true;
if (!tooClose)
{
found = true;
state.ActivePoints.Add(q);
state.Points.Add(q);
state.Grid[(int)qIndex.x, (int)qIndex.y] = q;
}
}
}
return found;
}
static Vector2 GenerateRandomAround(Vector2 center, float minimumDistance)
{
var d = RandomHelper.Random.NextDouble();
var radius = minimumDistance + minimumDistance * d;
d = RandomHelper.Random.NextDouble();
var angle = MathHelper.TwoPi * d;
var newX = radius * Math.Sin(angle);
var newY = radius * Math.Cos(angle);
return new Vector2((float)(center.x + newX), (float)(center.y + newY));
}
static Vector2 Denormalize(Vector2 point, Vector2 origin, double cellSize)
{
return new Vector2((int)((point.x - origin.x) / cellSize), (int)((point.y - origin.y) / cellSize));
}
}
public static class RandomHelper
{
public static readonly System.Random Random = new System.Random();
}
public static class MathHelper
{
public const float Pi = (float)Math.PI;
public const float HalfPi = (float)(Math.PI / 2);
public const float TwoPi = (float)(Math.PI * 2);
}
}
figures_Included:
public static bool figures_Included(float xPoint, float yPoint, float[] metricIn, int n)
{
float X = xPoint;
float Y = yPoint;
int npol = n;
int i, j;
bool res = false;
float[] XYpol = metricIn;
for (i = 0, j = npol - 1; i < npol; j = i++)
{
if ((((XYpol[i * 2 + 1] <= Y) && (Y < XYpol[j * 2 + 1])) ||
((XYpol[j * 2 + 1] <= Y) && (Y < XYpol[i * 2 + 1]))) &&
(X < (XYpol[j * 2] - XYpol[i * 2]) * (Y - XYpol[i * 2 + 1]) /
(XYpol[j * 2 + 1] - XYpol[i * 2 + 1]) + XYpol[i * 2]))
{
res = !res;
}
}
return res;
}
and InMetric :
static public InMetric getmetricIn(List<Vector3> drawcoord, bool editingmode = true)
{
float mapoffsetx = 0;
float mapoffsety = 0;
if (editingmode == true)
{
mapoffsetx = Main.mainSatting.mapoffsetx;
mapoffsety = Main.mainSatting.mapoffsetz;
}
else
{
mapoffsetx = 0;
mapoffsety = 0;
}
if (drawcoord[0].x != drawcoord[drawcoord.Count - 1].x && drawcoord[0].z != drawcoord[drawcoord.Count - 1].z) //если линия, ограничивающая полигон не замкнута
drawcoord.Add(drawcoord[0]); //добавляем замыкающую вершину
float[] metricIn = new float[drawcoord.Count * 2]; //дополнительный массив вершин, пересчитанный для проверки нахождения точки внутри полигона
drawcoord[0] = new Vector3(drawcoord[0].x - mapoffsetx, 0, drawcoord[0].z - mapoffsety); //расчет 0-ой вершины в единицах Unity (метры)
metricIn[0] = drawcoord[0].x;
metricIn[1] = drawcoord[0].z; //запись 0-ой вершины в дополнительный массив. x-координаты под четными индексами, Z-координаты под нечетными индексами
float minpointx = drawcoord[0].x; //минимальная x-координата
float maxpointx = drawcoord[0].x; //максимальная х-координата
float minpointz = drawcoord[0].z; //минимальная y-координата
float maxpointz = drawcoord[0].z; //максимальная у-координата
/*Цикл обработки вершин. начинается 1-ой вершины*/
for (int i = 1; i < drawcoord.Count; i++)
{
drawcoord[i] = new Vector3(drawcoord[i].x - mapoffsetx, 0, drawcoord[i].z - mapoffsety); //расчет i-ой вершины в единицах Unity (метры)
metricIn[i * 2] = drawcoord[i].x; //запись i-ой вершины в дополнительный массив. x-координаты под четными индексами
metricIn[i * 2 + 1] = drawcoord[i].z; //запись i-ой вершины в дополнительный массив. z-координаты под нечетными индексами
/*поиск максимальных и минимальных координат по x и максимальных и минимальных координат по z*/
if (drawcoord[i].x < minpointx)
minpointx = drawcoord[i].x;
if (drawcoord[i].x > maxpointx)
maxpointx = drawcoord[i].x;
if (drawcoord[i].z < minpointz)
minpointz = drawcoord[i].z;
if (drawcoord[i].z > maxpointz)
maxpointz = drawcoord[i].z;
}
InMetric metric = new InMetric();
metric.metricIn = metricIn;
metric.minpointx = minpointx;
metric.maxpointx = maxpointx;
metric.minpointz = minpointz;
metric.maxpointz = maxpointz;
metric.drawcoord = drawcoord;
metric.count = drawcoord.Count;
return metric;
}
public class InMetric
{
public float minpointx { get; set; }
public float maxpointx { get; set; }
public float minpointz { get; set; }
public float maxpointz { get; set; }
public float[] metricIn { get; set; }
public List<Vector3> drawcoord { get; set; }
public int count { get; set; }
}
I really hope you guys can help me with my problem, this was my last resort and im super frustrated.
I'm creating a 2D Side-Scroller game and while coding the player file, I've ran into a very annoying thing that I don't know where the problem is. Everything else in the player is fine, what happens is that if the player is walking on a slant, and then comes off; the gravity (I'm assuming) is being messed with and when your in the air he just floats down instead of falling; also if you jump (after walking on the slant) he just does a teeeeeeny tiny hop. I have debugged the whole file several times and can't seem to figure it out.
If someone would please help, I'll put the whole player file. If you have a 2D sidescroller game in unity, you can just put this file on a gameobject with a rigidBody2D and isKinemic is true..
using UnityEngine;
using System.Collections;
using System;
public class PlayerControl : MonoBehaviour {
private Animator anim;
public static PlayerControl instance;
public static bool isShooting;
[HideInInspector]
public bool facingRight;
private float normalSpeed;
private static readonly float slopeLimitTangent = Mathf.Tan(75f * Mathf.Deg2Rad);
public float maxSpeed = 8f;
private float speedAccelerationOnGround = 10f;
private float speedAccelerationInAir = 5f;
private Vector2 velocity {get {return vel;}}
public int health = 100;
private bool isDead;
private const float skinWidth = .02f;
private const int horizRays = 8;
private const int vertRays = 4;
public enum JumpBehavior {
JumpOnGround,
JumpAnywhere,
CantJump
};
public JumpBehavior jumpWhere;
private float jumpIn;
public float jumpFreq = 0.25f;
public float jumpMag = 16;
public LayerMask whatIsGround;
private bool grounded { get { return colBelow; } }
private bool cooldown;
public GameObject standingOn {get; private set;}
public Vector3 platformVelocity {get;private set;}
public bool canJump { get {
if (jumpWhere == JumpBehavior.JumpAnywhere)
return jumpIn <= 0;
if (jumpWhere == JumpBehavior.JumpOnGround)
return grounded;
return false;
}
}
public bool colRight { get; set;}
public bool colLeft { get; set;}
public bool colAbove{ get; set;}
public bool colBelow{ get; set;}
public bool upSlope{ get; set;}
public bool downSlope{get;set;}
public float slopeAngle {get;set;}
public bool hasCollisions { get { return colRight || colLeft || colAbove || colBelow; }
}
private float
vertDistanceBetweenRays,
horizDistanceBetweenRays;
private Vector3 raycastTopLeft;
private Vector3 raycastBottomRight;
private Vector3 raycastBottomLeft;
private Vector2 maxVelocity = new Vector2(float.MaxValue,
float.MaxValue);
private Vector2 vel;
[Range(0, 90)]
public float slopeLimit = 30;
public float gravity = -15;
private GameObject lastStandingOn;
private Vector3 activeGlobalPlatformPoint;
private Vector3 activeLocalPlatformPoint;
public static int scene = 0;
void Start () {
instance = this;
anim = GetComponent<Animator> ();
float colliderWidth = GetComponent<BoxCollider2D>().size.x * Mathf.Abs
(transform.localScale.x) - (2 * skinWidth);
horizDistanceBetweenRays = colliderWidth / (vertRays - 1);
float colliderHeight = GetComponent<BoxCollider2D>().size.y * Mathf.Abs
(transform.localScale.y) - (2 * skinWidth);
vertDistanceBetweenRays = colliderHeight / (horizRays - 1);
}
void Update () {
if (!isDead)
HandleInput();
float movementFactor = grounded ? speedAccelerationOnGround : speedAccelerationInAir;
if (isDead)
HorizForce(0);
else
HorizForce(Mathf.Lerp(velocity.x, normalSpeed * maxSpeed, Time.deltaTime * movementFactor));
anim.SetBool("Grounded", grounded);
anim.SetBool("Dead", isDead);
anim.SetFloat("Speed", Mathf.Abs(velocity.x) / maxSpeed);
}
public void LateUpdate() {
jumpIn -= Time.deltaTime;
vel.y += gravity * Time.deltaTime;
Move (vel * Time.deltaTime);
}
public void AddForce(Vector2 force) {
vel += force;
}
public void SetForce(Vector2 force) {
vel = force;
}
public void HorizForce(float x) {
vel.x = x;
}
public void VertForce(float y) {
vel.y = y;
}
public void Jump() {
AddForce(new Vector2(0, jumpMag));
jumpIn = jumpFreq;
anim.SetTrigger("Jump");
}
void HandleInput() {
float h = Input.GetAxis("Horizontal");
normalSpeed = h;
if (h < 0) {
if (!facingRight)
Flip ();
facingRight = true;
} else
if (h > 0) {
if (facingRight)
Flip ();
facingRight = false;
} else
normalSpeed = 0;
if (canJump && Input.GetButtonDown("Jump"))
Jump();
if (Input.GetButton("melee") && !Input.GetButtonDown ("Fire1") && MeleeAttack.canHit) {
anim.SetTrigger ("Attack");
MeleeAttack.canHit = false;
MeleeAttack.instance.cooldown ();
}
}
private void Flip() {
transform.localScale = new Vector3(-transform.localScale.x, transform.localScale.y, transform.localScale.z);
facingRight = transform.localScale.x > 0;
}
void ResetColliders() {
colLeft = false;
colRight = false;
colAbove = false;
colBelow = false;
colLeft = false;
slopeAngle = 0;
}
void Move(Vector2 deltaMove) {
bool wasGrounded = colBelow;
ResetColliders();
HandlePlatforms ();
CalcRayOrigins();
if (deltaMove.y < 0 && wasGrounded)
HandleVerticalSlope(ref deltaMove);
if (Mathf.Abs(deltaMove.x) > 0.001f)
MoveHoriz(ref deltaMove);
MoveVert(ref deltaMove);
//CorrectHorizPlacement(ref deltaMove, true);
//CorrectHorizPlacement(ref deltaMove, false);
transform.Translate(deltaMove, Space.World);
if (Time.deltaTime > 0)
vel = deltaMove / Time.deltaTime;
vel.x = Mathf.Min(vel.x, maxVelocity.x);
vel.y = Mathf.Min(vel.y, maxVelocity.y);
if (upSlope)
vel.y = 0;
if (standingOn != null) {
activeGlobalPlatformPoint = transform.position;
activeLocalPlatformPoint = standingOn.transform.InverseTransformPoint(transform.position);
if (lastStandingOn != standingOn) {
if (lastStandingOn != null)
lastStandingOn.SendMessage("ControllerExit2D", this, SendMessageOptions.DontRequireReceiver);
standingOn.SendMessage("ControllerEnter2D", this, SendMessageOptions.DontRequireReceiver);
lastStandingOn = standingOn;
} else if (standingOn != null)
standingOn.SendMessage("ControllerStay2D", this, SendMessageOptions.DontRequireReceiver);
else if (lastStandingOn != null) {
lastStandingOn.SendMessage("ControllerExit2D", this, SendMessageOptions.DontRequireReceiver);
lastStandingOn = null;
}
}
}
void MoveHoriz(ref Vector2 deltaMove) {
bool goingRight = deltaMove.x > 0;
float rayDistance = Mathf.Abs (deltaMove.x) + skinWidth;
Vector2 rayDirection = goingRight ? Vector2.right : -Vector2.right;
Vector3 rayOrigin = goingRight ? raycastBottomRight : raycastBottomLeft;
for (int i = 0; i < horizRays; i++) {
Vector2 rayVect = new Vector2(rayOrigin.x, rayOrigin.y + (i * vertDistanceBetweenRays));
Debug.DrawRay(rayVect, rayDirection * rayDistance, Color.red);
RaycastHit2D raycastHit = Physics2D.Raycast(rayVect, rayDirection, rayDistance, whatIsGround);
if (!raycastHit) continue;
if (i == 0 && HandleHorizontalSlope(ref deltaMove, Vector2.Angle(raycastHit.normal, Vector2.up), goingRight))
break;
deltaMove.x = raycastHit.point.x - rayVect.x;
rayDistance = Mathf.Abs (deltaMove.x);
if (goingRight) {
deltaMove.x -= skinWidth;
colRight = true;
} else {
deltaMove.x += skinWidth;
colLeft = true;
}
if (rayDistance < skinWidth + .0001f)
break;
}
}
private void HandlePlatforms() {
if (standingOn != null) {
Vector3 newGlobalPlatformPoint = standingOn.transform.TransformPoint(activeLocalPlatformPoint);
Vector3 moveDistance = newGlobalPlatformPoint - activeGlobalPlatformPoint;
if (moveDistance != Vector3.zero)
transform.Translate(moveDistance, Space.World);
platformVelocity = (newGlobalPlatformPoint - activeGlobalPlatformPoint) / Time.deltaTime;
} else
platformVelocity = Vector3.zero;
standingOn = null;
}
private void MoveVert(ref Vector2 deltaMovement) {
bool isGoingUp = deltaMovement.y > 0;
float rayDistance = Mathf.Abs(deltaMovement.y) + skinWidth;
Vector2 rayDirection = isGoingUp ? Vector2.up : -Vector2.up;
Vector2 rayOrigin = isGoingUp ? raycastTopLeft : raycastBottomLeft;
rayOrigin.x += deltaMovement.x;
float standingOnDistance = float.MaxValue;
for (int i = 0; i < vertRays; i++) {
Vector2 rayVector = new Vector2(rayOrigin.x + (i * horizDistanceBetweenRays), rayOrigin.y);
Debug.DrawRay(rayVector, rayDirection * rayDistance, Color.red);
RaycastHit2D rayCastHit = Physics2D.Raycast(rayVector, rayDirection, rayDistance, whatIsGround);
if (!rayCastHit)
continue;
if (!isGoingUp) {
float verticalDistanceToHit = transform.position.y - rayCastHit.point.y;
if (verticalDistanceToHit < standingOnDistance) {
standingOnDistance = verticalDistanceToHit;
standingOn = rayCastHit.collider.gameObject;
}
}
deltaMovement.y = rayCastHit.point.y - rayVector.y;
rayDistance = Mathf.Abs(deltaMovement.y);
if (isGoingUp) {
deltaMovement.y -= skinWidth;
colAbove = true;
} else {
deltaMovement.y += skinWidth;
colBelow = true;
}
if (!isGoingUp && deltaMovement.y > .0001f)
upSlope = true;
if (rayDistance < skinWidth + .0001f)
break;
}
}
private void HandleVerticalSlope(ref Vector2 deltaMove) {
float center = (raycastBottomLeft.x + raycastBottomRight.x) / 2;
Vector2 direction = -Vector2.up;
float slopeDistance = slopeLimitTangent + (raycastBottomRight.x - center);
Vector2 slopeRayVector = new Vector2(center, raycastBottomLeft.y);
Debug.DrawRay(slopeRayVector, direction * slopeDistance, Color.yellow);
RaycastHit2D rayCastHit = Physics2D.Raycast(slopeRayVector, direction, slopeDistance, whatIsGround);
if (!rayCastHit)
return;
float angle = Vector2.Angle(rayCastHit.normal, Vector2.up);
if (Mathf.Abs (angle) < .0001f)
return;
downSlope = true;
slopeAngle = angle;
deltaMove.y = rayCastHit.point.y - slopeRayVector.y;
transform.rotation = Quaternion.Euler (0, 0, facingRight ? angle : -angle);
}
private bool HandleHorizontalSlope(ref Vector2 deltaMove, float angle, bool isGoingRight) {
if (Mathf.RoundToInt(angle) == 90)
return false;
if (angle > slopeLimit) {
deltaMove.x = 0;
return true;
}
if (deltaMove.y > .07f)
return true;
deltaMove.x += isGoingRight ? -skinWidth : skinWidth;
deltaMove.y = Mathf.Abs(Mathf.Tan(angle * Mathf.Deg2Rad) * deltaMove.x);
upSlope = true;
colBelow = true;
return true;
}
void CalcRayOrigins() {
Vector2 size = new Vector2(GetComponent<BoxCollider2D>().size.x * Mathf.Abs(transform.localScale.x), GetComponent<BoxCollider2D>().size.y * Mathf.Abs(transform.localScale.y)) / 2;
Vector2 center = new Vector2(GetComponent<BoxCollider2D>().center.x * transform.localScale.x, GetComponent<BoxCollider2D>().center.y * transform.localScale.y);
raycastTopLeft = transform.position + new Vector3(center.x - size.x + skinWidth, center.y + size.y - skinWidth);
raycastBottomRight = transform.position + new Vector3(center.x + size.x - skinWidth, center.y - size.y + skinWidth);
raycastBottomLeft = transform.position + new Vector3(center.x - size.x + skinWidth, center.y - size.y + skinWidth);
}
void CorrectHorizPlacement(ref Vector2 deltaMove, bool isRight) {
float halfWidth = (GetComponent<BoxCollider2D> ().size.x * transform.localScale.x) / 2f;
Vector3 rayOrigin = isRight ? raycastBottomRight : raycastBottomLeft;
if (isRight)
rayOrigin.x -= (halfWidth + skinWidth);
else
rayOrigin.x += (halfWidth + skinWidth);
Vector2 rayDirection = isRight ? Vector2.right : -Vector2.right;
float offset = 0;
for (int i = 1; i < horizRays - 1; i++) {
Vector2 rayVector = new Vector2(deltaMove.x + rayOrigin.x, deltaMove.y + rayOrigin.y + (i * vertDistanceBetweenRays));
RaycastHit2D raycastHit = Physics2D.Raycast(rayVector, rayDirection, halfWidth, whatIsGround);
if (!raycastHit) continue;
offset = isRight ? ((raycastHit.point.x - transform.position.x) - halfWidth) : (halfWidth - (transform.position.x - raycastHit.point.x));
deltaMove.x += offset;
}
}
}
please someone help.