I want to rotate camera around an fbx object when a key is being pressed using unity 3d.How it do? I tried some examples but its not working. First i create a game object and add main camera child of it.
public class CameraOrbit : MonoBehaviour
{
public Transform target;
public float speed = 1f;
private float distance;
private float currentAngle = 0;
void Start()
{
distance = (new Vector3(transform.position.x, 0, transform.position.z)).magnitude;
}
void Update()
{
currentAngle += Input.GetAxis("Horizontal") * speed * Time.deltaTime;
Quaternion q = Quaternion.Euler(0, currentAngle, 0);
Vector3 direction = q * Vector3.forward;
transform.position = target.position - direction * distance + new Vector3(0, transform.position.y, 0);
transform.LookAt(target.position);
}
}
I dont have access to unity at the moment so i might have messed something up.
The idea is keep an angle that you change based on input. Create a Quaternion from the angle (the Quaternion say how to rotate a vector to a certain direction), then rotate a Vector to that direction. Starting from the targets position move in that direction a certain distance and then look at the targets position.
This only implements rotation around the y axis, if you want rotation around the x axis all you need is another angle variable and then change to this Quaternion.Euler(currentAngleX, currentAngleY, 0);
Related
I made a circle and attach a lazer box on top of it.
The lazer will fire a raycast to its upper y axis (straight up). I also add a line renderer to view it.
I want the raycast to rotate 90 degrees back and forth. Sort of like its scanning everything on top. My problem is that its not working properly. It does rotate back and forth but If I move the x position of the lazer object, the raycast will rotate in a weird angle.
Script for lazer object
public LineRenderer lineRenderer;
public LayerMask layerMask;
public float laserSpeed;
Vector3 pointA;
Vector3 pointB;
Vector3 castPosition;
RaycastHit2D rayCast;
float time;
void Start()
{
pointA = transform.eulerAngles + new Vector3(0f, 0f, 90f);
pointB = transform.eulerAngles + new Vector3(0f, 0f, -90f);
}
void Update()
{
time = Mathf.PingPong(Time.time * laserSpeed, 1);
transform.eulerAngles = Vector3.Lerp(pointA, pointB, time);
castPosition = new Vector3(transform.position.x, transform.position.y, transform.position.z);
rayCast = Physics2D.Raycast(castPosition, transform.TransformDirection(Vector2.up), 10f, layerMask);
lineRenderer.SetPosition(0, castPosition);
lineRenderer.SetPosition(1, transform.TransformDirection(Vector2.up) * 10f);
}
Using eulerAngles for continuous animations is quite "dangerous". Unity stores the rotations as Quaternion and there are multiple ways of how to represent these in euler space!
When you read the .eulerAngles property, Unity converts the Quaternion's internal representation of the rotation to Euler angles. Because, there is more than one way to represent any given rotation using Euler angles, the values you read back out may be quite different from the values you assigned. This can cause confusion if you are trying to gradually increment the values to produce animation.
To avoid these kinds of problems, the recommended way to work with rotations is to avoid relying on consistent results when reading .eulerAngles particularly when attempting to gradually increment a rotation to produce animation. For better ways to achieve this, see the Quaternion * operator.
so you should rather go for Quaternion and do e.g.
And then you are using transform.TransformDirection(Vector2.up) which is a direction and pass it to your line renderer as a position.
What you want there is rather the position combined from
transform.position + transform.up
So together it should probably rather be
public LineRenderer lineRenderer;
public LayerMask layerMask;
public float laserSpeed;
private Quaternion originalRotation;
private Quaternion minRotation;
private Quaternion maxRotation;
void Start()
{
originalRotation = transform.rotation;
minRotation = originalRotation * Quaternion.Euler(0, 0, -90);
maxRotation = originalRotation * Quaternion.Euler(0, 0, 90);
}
void Update()
{
// Note that Vector3 is a "struct" -> there is no need to manually use "new Vector3(transform.position.x, ...)"
var startPosition = transform.position;
lineRenderer.SetPosition(0, startPosition);
var factor = Mathf.PingPong(Time.time * laserSpeed, 1);
// instead of the eulers rather use Quaternion
transform.rotation = Quaternion.Lerp(minRotation, maxRotation, factor);
// "transform.up" basically equals using "transform.TransformDirection(Vector3.up)"
var rayCast = Physics2D.Raycast(startPosition, transform.up, 10f, layerMask);
if(rayCast.collider)
{
// when you hit something actually use this hit position as the end point for the line
lineRenderer.SetPosition(1, rayCast.point);
}
else
{
// otherwise from the start position go 10 units in the up direction of your rotated object
lineRenderer.SetPosition(1, startPosition + transform.up * 10f);
}
}
I'm working on a little 2d game where you control a planet to dodge incoming asteroids. I'm implementing gravity in the following manner:
public class Gravity : MonoBehaviour
{
Rigidbody2D rb;
Vector2 lookDirection;
float lookAngle;
[Header ("Gravity")]
// Distance where gravity works
[Range(0.0f, 1000.0f)]
public float maxGravDist = 150.0f;
// Gravity force
[Range(0.0f, 1000.0f)]
public float maxGravity = 150.0f;
// Your planet
public GameObject planet;
void Start()
{
rb = GetComponent<Rigidbody2D>();
}
void Update()
{
// Distance to the planet
float dist = Vector3.Distance(planet.transform.position, transform.position);
// Gravity
Vector3 v = planet.transform.position - transform.position;
rb.AddForce(v.normalized * (1.0f - dist / maxGravDist) * maxGravity);
// Rotating to the planet
lookDirection = planet.transform.position - transform.position;
lookAngle = Mathf.Atan2(lookDirection.y, lookDirection.x) * Mathf.Rad2Deg;
transform.rotation = Quaternion.Euler(0f, 0f, lookAngle);
}
}
The problem is that the asteroids are attracted to the initial spawn point of the planet (0,0), it doesn't update in real time with the movement of the planet. So if I move the planet to the corner of the screen, the asteroids are still attracted to the centre of it.
Is there a way to solve this?
Thank you very much and excuse any flagrant errors!
There are 2 ways to get to an object with speed:
get the object to the player and in each update just use the planet.transform.position
using look at first to rotate to the plant and then using vector3.forword as the direction of the movement.
The first solution doesn't work for you so you might want to try the second one.
any way, if your lookAt part doesn't work too you can use
Vector3 dir = target.position - transform.position;
float angle = Mathf.Atan2(dir.y,dir.x) * Mathf.Rad2Deg;
transform.rotation = Quaternion.AngleAxis(angle, Vector3.forward);
or
Vector3 targetPos = target.transform.position;
Vector3 targetPosFlattened = new Vector3(targetPos.x, targetPos.y, 0);
transform.LookAt(targetPosFlattened);
As shown in the picture above, I have two GameObjects: the car and the circle. The car follows the circle, and the circle is moving with the cursor. Currently, my car is following the circle from a distance. When the circle moves along the x-axis, I want to rotate the car like it's drifting.
Here is my car follow script:
public class Follow : MonoBehaviour
{
public Transform leader;
public float followSharpness = 0.1f;
Vector3 _followOffset;
void Start()
{
// Cache the initial offset at time of load/spawn:
_followOffset = transform.position - leader.position;
}
void LateUpdate()
{
// Apply that offset to get a target position.
Vector3 targetPosition = leader.position + _followOffset;
//GetComponent<Rigidbody2D>().rotation = 1.5f;
// Keep our y position unchanged.
//targetPosition.y = transform.position.y;
// Smooth follow.
transform.position += (targetPosition - transform.position) * followSharpness;
}
}
You could try to use Transform.LookAt:
void LateUpdate()
{
Vector3 targetPosition = leader.position + _followOffset;
transform.position += (targetPosition - transform.position) * followSharpness;
transform.LookAt(leader);
}
Disclaimer: I'm not able to test that this code works right now, you'll have to try it out and see if it produces the desired result.
So from what you described, is you want to make the car always facing the cursor, so it is always "looking at" the cursor, here is how you can do it:
Vector3 diff = Camera.main.ScreenToWorldPoint(Input.mousePosition) - transform.position;
diff.Normalize();
float rot_z = Mathf.Atan2(diff.y, diff.x) * Mathf.Rad2Deg;
transform.rotation = Quaternion.Euler(0f, 0f, rot_z - 90);
From Answer: LookAt 2D Equivalent ?
I want to change the position of the object to the position of the mouse, moving slowly from first to second position.
My object is moving slowly to the random direction which appears to be connected with lower-left corner. When I go higher than the corner my object is moving upwards, same with left and right.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Rocket : MonoBehaviour
{
public float speed = 10f;
private Vector3 shippos;
void Start()
{
shippos = transform.position;
}
void FixedUpdate()
{
if (Input.mousePosition.x > shippos.x)
shippos.x=shippos.x+speed*Time.deltaTime;
if (Input.mousePosition.x < shippos.x)
shippos.x=shippos.x-speed*Time.deltaTime;
if (Input.mousePosition.y > shippos.y)
shippos.y=shippos.y+speed*Time.deltaTime;
if (Input.mousePosition.y < shippos.y)
shippos.y=shippos.y-speed*Time.deltaTime;
transform.position = shippos;
}
}
The mouse position is returned in screenspace coordinates. What you need to do is convert this to world coordinates so that they are compared in the same coordinate space as the transform (shippos).
void FixedUpdate()
{
if (Camera.main.ScreenToWorldPoint(Input.mousePosition).x > shippos.x)
shippos.x = shippos.x + speed * Time.deltaTime;
if (Camera.main.ScreenToWorldPoint(Input.mousePosition).x < shippos.x)
shippos.x = shippos.x - speed * Time.deltaTime;
if (Camera.main.ScreenToWorldPoint(Input.mousePosition).y > shippos.y)
shippos.y = shippos.y + speed * Time.deltaTime;
if (Camera.main.ScreenToWorldPoint(Input.mousePosition).y < shippos.y)
shippos.y = shippos.y - speed * Time.deltaTime;
transform.position = shippos;
}
If I did not misunderstand, you want to change your player's position straight to the point of mouse's position and looking towards mouse.
void Update() {
Transform target = mousePosition; //get your mouse position per frame
Vector3 relativePos = target.position - transform.position; //create a vector3 between them
Quaternion rotation = Quaternion.LookRotation(relativePos); //then give a rotation your player towards this vector.
transform.rotation = rotation; //and apply it.
}
Taken from here: http://answers.unity3d.com/questions/633873/how-to-make-an-object-move-towards-the-mouse-point.html
public float moveSpeed = 2.0; // Units per second
void Update () {
var targetPos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
targetPos.z = transform.position.z;
transform.position = Vector3.MoveTowards(transform.position, targetPos, moveSpeed * Time.deltaTime);
}
May not be accurate C#, but you get the idea.
i guess you are doing wrong , because wile you have Mathf.Lerp you Dont need to go as that clumsy way
Here is a video tutorial from youtube for mathf.lerp
and here is the base code:
someValue = Mathf.Lerp(initialValue , finalValue , Time.deltaTime * smoothness);
just take a look to the youtube link you will definitely get the idea!
AS A SIDE NOTE
you dont need to do alot of stuff to decrease your game performance! be careful about this kinda coding!
I'm creating a Google Cardboard VR app in Unity. I want the camera to constantly move forwards horizontally in the direction the camera is facing but not change its Y position, i.e. not rise or fall.
I've managed to get it so that the camera moves forwards in whichever direction it's looking but can go up and down if you look that way, using this line of code:
transform.position = transform.position + cam.transform.forward * WalkingSpeed * Time.deltaTime;
Is there a simple way of fixing the Y axis, so that I get the behaviour I'm looking for? Here's the full code so far:
using UnityEngine;
using System.Collections;
public class CameraMovement : MonoBehaviour {
public float WalkingSpeed = 1.0f;
public bool WalkEnabled = true;
GameObject cam;
void Start () {
// This is the part of the Cardboard camera where I'm getting
// the forward position from:
cam = GameObject.FindWithTag("CCHead");
}
void Update ()
{
if (WalkEnabled)
{
walk();
}
}
void walk()
{
transform.localPosition = transform.localPosition + cam.transform.forward * WalkingSpeed * Time.deltaTime;
}
}
Note: ticking the 'freeze position' y value in rigidbody constraints doesn't work.
Many thanks in advance.
You can try and split the forward vector up and build a new one where the y axis does not change:
transform.position =
transform.position +
new Vector3(
cam.transform.forward.x * WalkingSpeed * Time.deltaTime,
0, // add 0 to keep the y coordinate the same
cam.transform.forward.z * WalkingSpeed * Time.deltaTime);