Unity - following finger only works for one direction - unity3d

I have made some code that should make my player move into the direction of the finger:
if (Input.touchCount == 1 && Input.GetTouch(0).phase == TouchPhase.Moved)
{
Vector2 pos = Camera.main.ScreenToWorldPoint(new Vector3(Input.GetTouch(0).position.x, Input.GetTouch(0).position.y, 0));
if (pos.x < rb.position.x)
{
movehorizontal = -1;
}
if(pos.x > rb.position.x)
{
movehorizontal = 1;
}
if (pos.y < rb.position.z)
{
movevertical = -1;
}
if(pos.y > rb.position.z)
{
movevertical = 1;
}
}
Vector3 movement = new Vector3(movehorizontal, 0.00f, movevertical)*speed;
It's a 3D game, with a top-view, so my player starts at 0,0,0 and only moves along the x and z axis. My camera is positionated on 0,10,3. The following works on the x axis, so when my finger touches on the right side it goes to the right, if on the left to the left, but no matter where I touch it, it will only move to the front and not to the bottom of my screen.
I tried debugging, but the instructions werent working at the time.

screentoWorldPoint should be stored as a vector3. also since the camera is 10 units away from your plane the last parameter should be 10.
edit, that will only work for a cam pointing straight down. this code should work regardless of the camera angle.
Vector3 pos = Camera.main.ScreenToWorldPoint(new Vector3(Input.GetTouch(0).position.x, Input.GetTouch(0).position.y, 1f));
Vector3 pointDelta = pos - Camera.main.transform.position;
float multiplier = -Camera.main.transform.position.y / pointDelta.y;
pos = Camera.main.transform.position + pointDelta * multiplier;
finally these lines should compare the z values to each other
if (pos.z < rb.position.z)
if(pos.z > rb.position.z)
make those changes and let us know if any other problems still exist

Related

Unity quaternion lookrotation behaving oddly

I am using unity to create an airline game. I made the takeoff code as the following:
`
Rigidbody m_Rigidbody;
float thrust_x = 2;
float thrust_y = 0;
float timeRemaining = 1.5f;
// Start is called before the first frame update
void Start()
{
m_Rigidbody = GetComponent<Rigidbody>();
}
void TakeOff()
{
m_Rigidbody.AddForce(thrust_x, thrust_y, 0, ForceMode.Impulse);
transform.rotation = Quaternion.LookRotation(new Vector3(thrust_x, thrust_y, 0));
if (timeRemaining > 0)
{
timeRemaining -= Time.deltaTime;
}
else if (timeRemaining < 0 && thrust_y < 1.5)
{
thrust_y += 0.1f;
}
}
`
The timeRemaining waits for 1.5 seconds and then add to the thrust_y. The lookrotation makes the plane point in the direction of the impulse vector. This works impeccably with the plane as a cube. When I replaced it for a model, the plane strangely adds 90deg to the y rotation for no apparent reason.
Before running:
While running:
How can I make the plane once again point to 0,0. Turning the plane 90 and -90 at the start does not work, which gives reason that the value is being set, not changed.
Any help will be greatly appreciated. Thanks!

find the heading angle between 2 objects taking into account the forward angle of the initial object

Ok, so, i've been stuck on this for ages. Im working on an AI that will navigate a tank to a waypoint, defined as a Vector3. the position of the tank is also defines as a Vector3, both these have their Y position set to 0, as to ignore terrain elevation, the current rotation of the tank is also a Vector3, though only the Y rotation is needed, as i'm effectively projecting the 3d position onto a 2d navigational grid.
The AI passes anywhere between -1 and 1 into the control for the tank, which then handles the physics operations. so, i need to somehow calculate the angle, positive or negative in relation to the current heading angle of the tank to the position of the waypoint, then send the rotation value to the controls. At the moment I simply cant get it working, I feel like iv'e pretty much tried everything.
This is my code currently, it doesn't work, at all, and is about the 20th revision:
void driveToTarget()
{
Vector3 target0 = driveTarget;
target0.y = 0;
GameObject current0Obj = new GameObject();
Vector3 current0 = this.transform.position;
current0.y = 0;
print(current0);
print(target0);
Vector3 current0Angle = this.transform.eulerAngles;
print(current0Angle.y);
current0Angle.x = 0;
current0Angle.z = 0;
Vector3 heading = target0 - current0;
Quaternion headingAngle = Quaternion.LookRotation(heading);
print("headingAngle" + headingAngle);
print("heading direction, allegidly: " + Quaternion.Euler(heading).ToEulerAngles());
Quaternion distanceToGo = Quaternion.Lerp(Quaternion.Euler(current0Angle), headingAngle, 0.01f);
float angle = Vector3.SignedAngle(current0, target0, Vector3.up);
float difference = Mathf.Abs(angle - current0Angle.y);
print("heading angle " + angle);
if (current0 != driveTarget)
{
steeringVal = Mathf.Abs(1.5f-(1f/Mathf.Abs(distanceToGo.y))) * -Mathf.Sign(distanceToGo.y); ;
throttleVal = 0f;
} else
{
throttleVal = 0;
}
}
--EDIT--
So, I've partially solved it, and now encountered another problem, I've managded to get the tank to detect the angle between itself and the waypoint, BUT, rather than orienting forward towards the waypoint, the right side of the tank orients towards it, so it orbits the waypoint. I actually know why this is, becasue the forward vector of the tank is technically the right vector because of unity's stupid axis ruining my blender import, anyway, heres the updated code:
void driveToTarget()
{
Vector3 target0 = driveTarget;
target0.y = 0;
Vector3 current0 = this.transform.position;
current0.y = 0;
print("Current: " + current0);
print("Target: " + target0);
Vector3 current0Angle = this.transform.rotation.eulerAngles;
print("Curret rotation:" + current0Angle.y);
current0Angle.x = 0;
current0Angle.z = 0;
Vector3 heading = target0 - current0;
Quaternion headingAngle = Quaternion.LookRotation(heading);
print("heading angle: " + headingAngle.ToEuler());
float distanceToGo = (current0Angle.y) - headingAngle.eulerAngles.y;
print("DistanceToGo: " + distanceToGo);
if (current0 != driveTarget)
{
steeringVal = 1 * -Mathf.Sign(distanceToGo);
throttleVal = 0f;
} else
{
throttleVal = 0;
}
Debug.DrawRay(current0, heading, Color.red, 1);
Debug.DrawRay(current0, this.transform.up, Color.red, 1);
}
I'm not sure exactly how your code is setup or how the steering works. You may want to look into using the Unity NavMeshAgent to simplify this.
Regardless here is some code I wrote up that takes a destination and rotates an object towards it. All you'd have to do from there is move the object forwards.
Vector3 nextDestination = //destination;
Vector3 direction = nextDestination - transform.position;
direction = new Vector3(direction.x, 0, direction.z);
var newRotation = Quaternion.LookRotation(direction);
var finalRotation = Quaternion.Slerp(transform.rotation, newRotation, Time.deltaTime); //smoothes out rotation
transform.rotation = finalRotation;
Sorry if this isn't what you needed. Have you been able to figure out which part of the code is behaving unexpectedly from your print statements?

Translated grapple physics from Processing to Unity to get different results

tl;dr Moving my game from Processing to Unity. Code responsible for grappling by manually changing the player's velocity doesn't work even though it's basically copy/pasted.
Hi, I've been working on a project of mine over the summer on Processing, and last week I decided to translate it over to Unity.
What I'm having a problem with is the grapple/rope physics. It's supposed to essentially keep the player inside a circle (made by the endpoint of the rope and the length of the rope). When the player falls outside of this circle, the player's position is moved back to the edge of the circle and the player's velocity is set to tangent of the circle.
Decreasing the length of the rope while swinging is supposed to speed you up. (See Floating Point)
On Processing, it works perfectly just as described above, but when I basically copy/pasted the code into unity it loses momentum too quickly (always ends up stopping at the same angle on the other side the player started on). Here is the code for both (run on each physics frame):
(I've also made some images to describe the motion that both versions produce)
Processing
Code
(warning: bad and redundant)
physics update:
exists = (endPoint != null);
if(lgth<=0) lgth = 1;
if(exists) {
currentLength = phs.position.dist(endPoint);
if(currentLength > lgth) {
float angle = getAngle(endPoint, phs.position);
phs.addPosition(abs(currentLength - lgth), angle);
float angleBetween = getAngle(phs.position, endPoint);
PVector relativeVelocity = new PVector(phs.velocity.x + phs.position.x, phs.velocity.y + phs.position.y);
float displacement = angleBetween - 90;
Line l1 = lineFromTwoPoints(relativeVelocity, endPoint);
Line l2 = lineFromAngle(phs.position, displacement);
PVector pointToLerpTo = intersection(l1, l2);
if(pointToLerpTo!=null) {
phs.velocity.x = pointToLerpTo.x-phs.position.x;
phs.velocity.y = pointToLerpTo.y-phs.position.y;
}
else phs.velocity.mult(0);
}
}
when the player shortens the rope, speed increases:
if(exists) {
float newLgth = lgth-d;
float distance = getDistance(phs.position, endPoint);
if(distance > newLgth) {
float ratio = (distance-newLgth)/lgth;
phs.velocity.setMag(phs.velocity.mag()*(1+ratio));
}
lgth = newLgth;
}
Motion from Processing (good)
Player starts by moving downwards at left edge of rope circle. Doesn't lose speed and continues going around multiple times until gravity slows it down.
Unity
Code
both code blocks from above are handled in the same place here, under FixedUpdate() (problematic part seems to be the velocity section)
distance = Vector2.Distance(transform.position, endpoint);
if(connected && distance > length) {
//lerp position -> endpoint// keep gameObject within length of the rope
float posLerpAmount = (distance - length) / distance;
transform.position = Vector2.Lerp(transform.position, endpoint, posLerpAmount);
//'lerp' velocity -> endpoint// keep the velocity locked to the tangent of the circle around the endpoint
Vector2 relativeVelocity = GetComponent<Rigidbody2D>().velocity + (Vector2)transform.position;
Line l1 = Geometry.LineFromTwoPoints(relativeVelocity, endpoint);
Line l2 = Geometry.LineFromAngle(transform.position, Geometry.GetAngle(endpoint, transform.position) - 90);
if(!Geometry.AreParallel(l1, l2)) {
Vector2 pointToLerpTo = Geometry.Intersection(l1, l2) - (Vector2)transform.position;
GetComponent<Rigidbody2D>().velocity = pointToLerpTo;
}
else GetComponent<Rigidbody2D>().velocity = new Vector2(0, 0);
//increases the magnitude of the velocity based on how far the rope moved the object's position
float ratio = (distance - length) / length;
GetComponent<Rigidbody2D>().velocity *= 1 + ratio;
distance = length;
}
Motion from Unity (bad)
Player starts by moving downward at left edge of rope circle. Gains a little bit of speed from gravity, then will always stop 45 degrees on the other side where it started (regardless of starting speed), then slowly fall back down to the bottom of the circle.
If anyone needs me to explain the Geometry class (lines, intersections) then I can, but I think it's mostly self-explanatory. Otherwise, I think I explained this the best I could. Thanks in advance for any help.
(also, StackOverflow isn't letting me add the Unity2d tag so I guess I gotta settle for Unity3d)
I found out that Rigidbody2D.velocity.magnitude is not how far the object moves every physics update. This is what was causing the issue, because the Processing code was based off the velocity being added directly to the position every update.
To fix this, what I did was do the same geometry, but scale the velocity to the % of how much of the velocity was actually 'used' (it usually travels 2% of the actual velocity vector).
Here is the final code in Unity: (this time I'm showing the fill FixedUpdate(), with the irrelevant parts removed)
float lastMagnitude;
Vector2 lastPosition;
void FixedUpdate() {
float velocityMoved = Vector2.Distance(lastPosition, transform.position) / lastMagnitude;
Debug.Log(velocityMoved * 100 + "%"); //this is usually 2%
bool shortenedRope = false;
if(Input.GetButton("Shorten Rope")) {
shortenedRope = true;
length -= ropeShortenLength;
}
distance = Vector2.Distance(transform.position, endpoint);
if(connected && distance > length) {
//lerp position -> endpoint// keep gameObject within length of the rope
float posLerpAmount = (distance - length) / distance;
transform.position = Vector2.Lerp(transform.position, endpoint, posLerpAmount);
//'lerp' velocity -> endpoint// keep the velocity locked to the tangent of the circle around the endpoint
Vector2 adjustedVelocity = rigidbody.velocity * velocityMoved;
Vector2 relativeVelocity = adjustedVelocity + (Vector2)transform.position;
Line l1 = Geometry.LineFromTwoPoints(relativeVelocity, endpoint);
Line l2 = Geometry.LineFromAngle(transform.position, Geometry.GetAngle(endpoint, transform.position) - 90);
if(!Geometry.AreParallel(l1, l2)) {
Vector2 pointToLerpTo = Geometry.Intersection(l1, l2) - (Vector2)transform.position;
rigidbody.velocity = pointToLerpTo;
rigidbody.velocity /= velocityMoved;
}
else rigidbody.velocity = new Vector2(0, 0);
//'give back' the energy it lost from moving it's position
if(shortenedRope) {
float ratio = (distance - length) / length;
rigidbody.velocity *= 1 + ratio;
}
distance = length;
}
lastPosition = transform.position;
lastMagnitude = rigidbody.velocity.magnitude;
}
EDIT: Recently learned that it is better to use Time.deltaFixedTime instead of the variable I made velocityMoved, since Time.deltaFixedTime is already calculated.

Tilt Control Similar to Temple run

I want to create tilt effect just like temple run.I have a character controller(player) in the game that is moving on its forward by controller.Move(transform.forward) after which I am apply tilt to it to lean it left and right .Previously for the tilt I tried modifying the player position by using transform.translate /tranform.position directly through the accelerometer readings like this :
mytransform.translate(acceleration.x*Time.delaTime*5.0f);
but that had a problem that when I shake the device my camera starts to jerk and the player also then I used the following code to create tilt on positive Z axis
Vector3 dir = new Vector3(accel.x*8f, 0,0);
if (dir.sqrMagnitude > 1)
{
dir.Normalize();
}
dir.x = Mathf.Round(dir.x * 10f) / 10f;
//mytemp is used for temp storage of player position added with the acceleration
mytemp = mytransform.position+(mytransform.right*dir.x*Time.deltaTime*5.0f);
Vector3 diffVec=Vector3.zero;
///position of the element on which the player is colliding;
Vector3 col_pos=Collidingelement.transform.position;
Vector3 unitvec=new Vector3(1,0,0);
//removing x and z of the collider
diffVec= Vector3.Scale(col_pos,unitvec);
//nullify the y,z of the updated mytransform position so that the distance is only measured on X
Vector3 ppos = Vector3.Scale(mytemp,unitvec);
//calculate the distance between player & colliding element
disti=Vector3.Distance( ppos,diffVec);
disti=Mathf.Clamp(disti,-1.5f,1.5f);
disti = Mathf.Round(disti * 10f) / 10f;
//update the player position and apply tilt to it if the distance is less than 1.5f
if(disti<=1.50f)
{
mytransform.position=mytemp;
}
now this has a problem that if lets say I have a value of 0.1 in the acceleration its keep on update my temp and if the distance is less my player will start leaning towards a side though I held my device on same position and acceleration value was always 0.1
Why don't you just calculate delta acceleration.
bool isMoved = false;
Vector2 lastAccel = Vector2.Zero;
Vector2 margin = new Vector2(0.05f, 0.05f); //not processing if its in margin.
Vector2 deltaAccel = currAccel - lastAccel ;
if(deltaAccel.x < margin.x)
{
//don't process
isMove = false;
}
else
{
isMove = true;
lastAccel = currAccel;
}
if(isMove)
{
//Process with deltaAccel here
}

Camera rotation with mouse but dont stop

I have a question I made a game where you controll an spacecraft and use the mouse/keyboard to move. I use the mouse to rotate the ship up, down left and right. Works like a charm. Only problem is when I stop moving the mouse the ship also stops. So If I want to rotate the ship a few times I need to run a marathon with my mouse. This is because I use the Input.Axis(Mouse X) and thats zero when you stop moving the mouse.
So what I want is: Rotate the ship lets say left if I move my mouse a bit to the left and only stop when I return the mouse to the centerarea. I have this code ATM
var c = Camera.main.transform;
float mouseX = Input.GetAxis("Mouse X");
c.Rotate(0, mouseX * sensitivity, 0);
c.Rotate(-Input.GetAxis("Mouse Y") * sensitivity, 0, 0);
c.Rotate(0, 0, -Input.GetAxis("QandE") * 90 * Time.deltaTime);
How can I accomplish this
BugFinder's answer is correct. Here it is in code, for rotating around the Y axis. You can build on it to get your other axes working.
using UnityEngine;
public class Roll : MonoBehaviour
{
public float sensitivity = .001f;
Transform c;
void Start()
{
c = Camera.main.transform;
}
void Update()
{
Vector3 mouse = Input.mousePosition;
float dx = 0;
if (mouse.x > 1000)
dx = mouse.x - 1000;
if (mouse.x < 920)
dx = mouse.x - 920;
c.Rotate(0, dx * sensitivity, 0);
}
}