I am making a top down game on Unity, so I am using the x and z axis as my plane. I have my character rotated x 90, y 0, z 0 so that it is flat on the plane. As soon as I hit play the character is rotated vertical?! I think it has something to do with my script to face the mouse position.
What it should look like:
When I hit play:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
public static float moveSpeed = 10f;
private Rigidbody rb;
private Vector3 moveInput;
private Vector3 moveVelocity;
// Update is called once per frame
void Start()
{
rb = GetComponent<Rigidbody>();
mainCamera = FindObjectOfType<Camera>();
}
void Update()
{
// Setting up movement along x and z axis. (Top Down Shooter)
moveInput = new Vector3(Input.GetAxis("Horizontal"), 0f, Input.GetAxis("Vertical"));
moveVelocity = moveInput * moveSpeed;
//Make character look at mouse.
var dir = Input.mousePosition - Camera.main.WorldToScreenPoint(transform.position);
var angle = Mathf.Atan2(dir.y, dir.x) * Mathf.Rad2Deg;
transform.rotation = Quaternion.AngleAxis(angle, Vector3.up);
}
void FixedUpdate()
{
// Allows character to move.
rb.velocity = moveVelocity;
}
}
Figured it out: I am answering my own question to help others.
Vector3 difference = Input.mousePosition - Camera.main.WorldToScreenPoint(transform.position);
float rotZ = Mathf.Atan2(difference.y, difference.x) * Mathf.Rad2Deg;
transform.rotation = Quaternion.Euler(90f, 0f, rotZ -90);
This does EXACTLY what I wanted!
Related
so my character has to walk around a tower, simple
but me being stupid can only work it out by using transform.position in update so jumping and collisions ofc, dont work
here is the tower concept ( see image )
Tower
here is how it works rn (see video: https://streamable.com/7tmq1l)
You will see in the clip how bad it breaks if i comment the transform.position = newposition to allow for jumping
Here is my code I used:
public class Movement : MonoBehaviour
{
[SerializeField] private float radius = 7;
[SerializeField] private float angleSpeed = 28;
[SerializeField] private float jumpForce = 5;
private float angle;
Rigidbody rb;
private void Start()
{
rb = GetComponent<Rigidbody>();
}
void Update()
{
transform.rotation = Quaternion.Euler(0, angle, 0);
float horizontalInput = Input.GetAxis("Horizontal");
angle -= horizontalInput * angleSpeed * Time.deltaTime;
Vector3 newPosition = Quaternion.Euler(0, angle, 0) * new Vector3(0, 0, radius);
transform.position = newPosition;
//jump
if(Input.GetKeyDown(KeyCode.Space)|| Input.GetKeyDown(KeyCode.W))
{
Debug.Log("Jumping!");
rb.AddForce(Vector3.up * jumpForce, ForceMode.Impulse);
}
}
Ofc the jumping doesnt work because of this
adjust the XZ position using the rigidBody and let the rb adjust the Y axis.
Vector3 newPosition = Quaternion.Euler(0, angle, 0) * radius;
newPosition.Y = rb.position.Y; // leave Y unchanged to allow for jumps
rb.position = newPosition;
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);
I want to use moverotation to rotate the object in the direction of the Main Camera, like a common third person shooter, but I don't know how to set the quaternion values or otherwise
`using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class movimento : MonoBehaviour
{
[SerializeField] float walk = 1;
[SerializeField] float run = 2;
Vector3 movement = Vector3.zero;
private Rigidbody rig;
// Start is called before the first frame update
void Start()
{
rig = GetComponent<Rigidbody>();
}
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown(KeyCode.LeftShift)) walk = (walk + run);
if (Input.GetKeyUp(KeyCode.LeftShift)) walk = (walk - run);
float Horizontal = Input.GetAxis("Horizontal");.
float Vertical = Input.GetAxis("Vertical");
movement = Camera.main.transform.forward * Vertical + Camera.main.transform.right * Horizontal;
float origMagnitude = movement.magnitude;
movement.y = 0f;
movement = movement.normalized * origMagnitude;
}
private void FixedUpdate ()
{
rig.MovePosition(rig.position + movement * walk * Time.fixedDeltaTime);
Quaternion rotation = Quaternion.Euler(???);
rig.MoveRotation(rig.rotation * rotation);
}
}`
i use a coroutine to do smooth rotation. I use Quaternion.LookRotation for the job.
so you indicate the position of object to look at and the duration of animation. Here you want to rotate face to the main camera
StartCoroutine(SmoothRotation(Camera.main.transform, 3f));
:
:
IEnumerator SmoothRotation(Transform target, float duration)
{
float currentDelta = 0;
var startrotation = transform.rotation;//use your rigisbody if you want here i use the gameobject
var LookPos = target.position - transform.position;
var finalrot = Quaternion.LookRotation(LookPos);
while (currentDelta <= 1f)
{
currentDelta += Time.deltaTime / duration;
transform.rotation = Quaternion.Lerp(startrotation, finalrot, currentDelta);//
yield return null;
}
transform.rotation = finalrot;
}
if you want to see (in scene when running) where your camera points just add this line of code in update():
Debug.DrawRay(Camera.main.transform.position, Camera.main.transform.TransformDirection(Vector3.forward) * 10f, Color.black);
if you want to point in same direction tha nthe Camera just change the line of finalrot in SmoothRotation Method:
var finalrot = Camera.main.transform.rotation;
you dont need to calculate the LookPos
for your problem of crazy rotation, i suggest you to reset rotation x and z
direction = hit.transform.position - transform.position;
Quaternion rotation = Quaternion.LookRotation(direction);
rotation.x = 0f;
rotation.z = 0f;
a tips to detect object what you want with the raycast inside spere : Physics.OverlapSphere: you could select what you want to cast when using the optional parameter layermask
private void DetectEnemy(Vector3 center, float radius)
{
var hitColliders = Physics.OverlapSphere(center, radius );
for (var i = 0; i < hitColliders.Length; i++)
{
print(hitColliders[i].name + "," + hitColliders[i].transform.position);
// collect information on the hits here
}
}
I created a raycast from the camera, and I would like to rotate the rigidbody to where the raycast is pointing but if i launch unity, it rotated wildly. What is the error?
Vector3 direction;
Vector3 rayDir = new Vector3(Screen.width/2,Screen.height/2);
void Update()
Ray ray = Camera.main.ScreenPointToRay(rayDir);
Debug.DrawRay(ray.origin, ray.direction * 10, Color.yellow);
RaycastHit hit = new RaycastHit ();
direction = hit.point - transform.position;
private void FixedUpdate ()
Quaternion rotation = Quaternion.LookRotation(direction);
rig.MoveRotation(rig.rotation * rotation);
Add a character controller component, this is what is for. See:
https://docs.unity3d.com/Manual/class-CharacterController.html
I'm trying to learn Unity3D and I'm using this tutorial to get started.
In my PlayerController below the "ball" rolls in the direction of the arrow key pressing. But my question is: When I press left or right arrow I don't want it to move in the direction but to turn in the direction.
So the ball moves forward/backward on arrow key up/down and rotate left/right on arrow key left/right.
public class PlayerController : MonoBehaviour {
public float speed;
private Rigidbody rb;
void Start()
{
rb = GetComponent<Rigidbody> ();
}
void FixedUpdate()
{
float moveHorizontal = Input.GetAxis("Horizontal");
float moveVertical = Input.GetAxis("Vertical");
Vector3 movement = new Vector3 (moveHorizontal, 0.0f, moveVertical);
rb.AddForce (movement * speed);
}
}
I've searched on google but haven't been able to find a solution.
UPDATE
Here is my camera controller.
public class CameraController : MonoBehaviour {
public GameObject player;
private Vector3 offset;
// Use this for initialization
void Start () {
offset = transform.position - player.transform.position;
}
// Update is called once per frame
void LateUpdate () {
transform.position = player.transform.position + offset;
}
}
float delta = Input.GetAxis("Horizontal");
Vector3 axis = Vector3.forward;
rb.AddTorque (axis * speed * delta);
or
transform.Rotate (axis * speed * delta);
Instead of:
rb.AddForce (movement * speed);
you can use:
rb.AddTorque (movement * speed);
This will add angular force to the ball.
I have a turret placed as a game-object ,i have set the target as enemy in inspector,but somehow the turrets just point towards my enemy but are not continuously rotating on z axis.what is the problem,any help thanx...!!
Here is my code
using UnityEngine;
using System.Collections;
public class TurretScript: MonoBehaviour
{
public Transform target;
void Update()
{
Vector3 tarPos = new Vector3(target.position.x, target.position.y, 10);
Vector3 lookPos = Camera.main.ScreenToWorldPoint(tarPos);
lookPos = lookPos - transform.position;
float angle = Mathf.Atan2(lookPos.y, lookPos.x) * Mathf.Rad2Deg;
transform.rotation = Quaternion.AngleAxis(angle, Vector3.forward);
}
}
Easiest way to achieve this? Cheat! Something like this:
public class TurretScript: MonoBehaviour
{
//values that will be set in the Inspector
public Transform Target;
public float RotationSpeed;
void Update()
{
var direction = Target.transform.position - transform.position;
// Set Y the same to make the rotations turret-like:
direction.y = transform.position.y;
var rot = Quaternion.LookRotation(direction, Vector3.up);
transform.rotation = Quaternion.RotateTowards(
transform.rotation,
rot,
RotationSpeed * Time.deltaTime);
}
}
You can also use Transform.LookAt() from the Documentation
I find this to be the simplest approach without the headache of computing rotations.