AI scripting in Unity. Blocking Y rotation in code - unity3d

I am creating a game where the world is 3D yet the characters are 2D. This means that my Y rotation must not change or else the 2D sprite rotates. I have a been scripting an AI and while the enemy does attract towards my player, he also rotates by 90 degrees. How can I modify my code to make it so that the sprite follows my player in the X and Z axis but the Y axis rotation stays zero.
//CODE STARTS
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class AISimple : MonoBehaviour
{
public Transform player;
float distancefrom_player;
public float look_range = 20.0f;
public float agro_range = 10.0f;
public float move_speed = 5.0f;
public float damping = 6.0f;
// Use this for initialization
void Start()
{
}
// Update is called once per frame
void Update()
{
distancefrom_player = Vector3.Distance(player.position, transform.position);
if (distancefrom_player < look_range)
{
lookAt();
}
if (distancefrom_player < agro_range)
{
attack();
}
}
void lookAt()
{
Quaternion rotation = Quaternion.LookRotation(player.position - transform.position);
transform.rotation = Quaternion.Slerp(transform.rotation, rotation, Time.deltaTime * damping);
}
void attack()
{
transform.Translate(Vector3.forward * move_speed * Time.deltaTime);
}
}

rigidbody has this functionality, if you tick freeze y rotation you'll be fine

okay, then try to modify y rotation before you set it
void lookAt()
{
Quaternion rotation = Quaternion.LookRotation(player.position - transform.position);
var euler = Quaternion.Slerp(transform.rotation, rotation, Time.deltaTime * damping).eulerAngles;
euler.y = 0f;
transform.rotation = Quaternion.Euler(euler);
}

Related

Unity2D - Enemy shoot at player in a cone shaped pattern

I am trying to set up an enemy that will shoot at the player in a cone shape/shotgun shape. If I set the projectile script to transform.position += transform.right * m_Speed * Time.deltaTime; then the cone shape works as intended, just only to the right and not in the direction of the player. With the current setup (below), the projectile will shoot at the player, but all the bullet prefabs will be on top of each other and all going in the same direction, not in a cone shape.
How can I adjust this so the enemy will shoot at the player but retain the cone shape?
Enemy Script
aimAngle = 60f;
for (int i = 0; i < spreadShot; i++)
{
var shotRotation = gameObject.transform.rotation;
shotRotation *= Quaternion.Euler(0, 0, aimAngle);
GameObject clone = Instantiate(projectile, new Vector2(gameObject.transform.position.x, gameObject.transform.position.y), shotRotation);
aimAngle = aimAngle - 30f;
Vector3 direction = (Vector3)((player.transform.position - transform.position));
direction.Normalize();
clone.GetComponent<Projectile>().Setup(direction);
}
Projectile.cs
[SerializeField] float m_Speed;
Vector3 shootDir;
public void Setup(Vector3 shootDir)
{
this.shootDir = shootDir;
}
private void Update()
{
transform.position += shootDir * m_Speed * Time.deltaTime;
}
Not perfect yet but here is a working solution if anyone else has the same question.
Enemy Script
[SerializeField] public float attackSpread;
[SerializeField] private float startShotTime;
[SerializeField] private float delayShotTime;
[HideInInspector] public int spreadShot;
public void Attack() {
Vector2 targetPosition = target.transform.position - aimIndicator.transform.position;
Vector2 dirTowardsTarget = (targetPosition - (Vector2)transform.position);
transform.right = targetPosition.normalized;
Quaternion newRot;
for (int i = 0; i < spreadShot; i++)
{
float addedOffset = (i - (spreadShot / 2)) * attackSpread;
newRot = Quaternion.Euler(transform.localEulerAngles.x,
transform.localEulerAngles.y,
transform.localEulerAngles.z + addedOffset);
Instantiate(projectile).GetComponent<ButcherProjectile>().SpawnBullet(transform.position, newRot);
}
}
Projectile Script
[SerializeField] private float MovementSpeed = 10;
private Vector2 velocity;
public void SpawnBullet(Vector3 position, Quaternion rotation)
{
transform.position = position;
transform.rotation = rotation;
velocity = transform.right.normalized * MovementSpeed;
}
public void Update()
{
Vector2 nextPosition = (Vector2)transform.position + (velocity * Time.deltaTime);
transform.position = nextPosition;
Destroy(gameObject, 2f);
}
At the moment, your code rotates the bullet itself, not the vector of direction towards player. Shot rotation you computed doesn't affect your direction in any way.
To elaborate, if you rotate an object and just move it by transform.position, you changed its position by exactly how you specified, as if you just changed its x, y or z component by hand. Your rotation change to an object would produce desired results if you used transform.Translate(params) as this operation is dependant on object's current rotation and scale.
Apply your rotation to the direction, it should work just fine :)
More reference on how to do it: https://answers.unity.com/questions/46770/rotate-a-vector3-direction.html

CHARACTER ROTATION depending on camera IN UNITY

I'm making a 3rd person controller in unity and i'm stuck: i can't figure out how to make the player follow my freelook cinemachine.
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
public float speed;
public GameObject Hoverboard_script;
public GameObject cinemachine_Hoverboard;
public Transform main_cam_tf;
void Update()
{
Hoverboard_script.SetActive(false);
cinemachine_Hoverboard.SetActive(false);
PlayerMovement_void();
CamController_void();
}
void PlayerMovement_void()
{
float hor = Input.GetAxisRaw("Horizontal");
float ver = Input.GetAxisRaw("Vertical");
Vector3 playerMovement = new Vector3(hor, 0f, ver).normalized * speed * Time.deltaTime;
transform.Translate(playerMovement, Space.Self);
}
void CamController_void()
{
float MouseY = main_cam_tf.eulerAngles.y;
Debug.Log(MouseY);
Quaternion rotation = Quaternion.Euler(0f, MouseY, 0f);
transform.rotation = Quaternion.Lerp(transform.rotation, rotation, Time.deltaTime * 4f);
}
}
Right now if i rotate the camera, the player enters a non-stop loop where it rotate constantly. How can i solve? Thanks, cheers
If you want to rotate the player as the rotation value of Y of Camera then remove all the lines of codes in which they rotate your object. Instead use one of these:
1.
transform.rotation = Quaternion.AngleAxis(Camera.Main.transform.eulerAngles.y, Vector3.up);
transform.rotation = Quaternion.EulerAngles(transform.eulerAngles.x, Camera.Main.transform.eulerAngles.y, transform.eulerAngles.z);

Rotate Camera vector to look at player Unity

I create a game, like minigolf/pool. I want to have a camera which follow player.
Position is normally ok, I get the ball direction and I lerp.
Rotation is almost ok. Currently, rotation by Y axis is ok, but camera look straigth forward, and don't look down to the player :
I already try many thing , quaternion angleToaxis, quarternion lookat ... but doesn't look good, the camera go look away ...
Here my code
namespace CameraManagerNameSpace
{
public class CameraManager : MonoBehaviour
{
public float cameraHeight=13f;
public PlayerNameSpace.Player playerToFollow;
public float followSpeed = 3f;
public float rotationSpeed = 1f;
float distance;
Vector3 position;
Vector3 newPos;
Quaternion rotation;
Quaternion newRot;
Vector3 playerPrevPos, playerMoveDir;
bool firstMoveDone=false;
void Start()
{
playerPrevPos = playerToFollow.player_transform.position;
distance = Vector3.Distance(transform.position,playerToFollow.player_transform.position);
}
void FixedUpdate()
{
if(Vector3.Distance(playerToFollow.player_transform.position ,playerPrevPos)>0.5f || firstMoveDone)
{
playerMoveDir = playerToFollow.player_transform.position - playerPrevPos;
firstMoveDone = true;
}
else
{
playerMoveDir = new Vector3(0,0,0);
}
if (playerMoveDir != Vector3.zero)
{
playerMoveDir.Normalize();
newPos = playerToFollow.player_transform.position - playerMoveDir * distance;
newRot =Quaternion.LookRotation(playerMoveDir,Vector3.up);
position = Vector3.Lerp(transform.position, new Vector3(newPos.x,newPos.y+cameraHeight,newPos.z), followSpeed * Time.deltaTime);
rotation = Quaternion.Lerp(transform.rotation, newRot, rotationSpeed * Time.deltaTime);
transform.position = position;
transform.rotation = rotation;
playerPrevPos = playerToFollow.player_transform.position;
}
}
}
}
Also, I don't know why, but after the balls stop the camera continue to do some movement very jerky, jolting, halting.
Well in
newRot = Quaternion.LookRotation(playerMoveDir,Vector3.up);
you are saying the camera to look in the same direction the player is moving ... not to look at the player. This would work if you wouldn't give the camera an extra position offset in the Y axis.
You might want to rather try
// vector pointing from the camera towards the player
var targetDirection = playerToFollow.player_transform.position - transform.position;
newRot = Quaternion.LookRotation(targetDirection, Vector3.up);
You should also rather use Update since FixedUpdate is only used for physics related stuff (also see Update & FixedUpdate)

How can I make an objects rotatable only for the player?

the problem is that if the player touches something that rotate, the player automatically starting rotating too because the object that is rotation right now pushed the player's colliders and and player starting rotating. I want to make my player un rotatable to another objects in the game but rotatable if the player rotate by himself
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class camera : MonoBehaviour
{
public enum RotationAxis
{
MouseX = 1,
MouseY = 2
}
public RotationAxis axes = RotationAxis.MouseX;
public float minimumVert = -45.0f;
public float maximumVert = 45.0f;
public float sensHorizontal = 10.0f;
public float sensVertical = 10.0f;
public float _rotationX = 0;
// Update is called once per frame
void Update()
{
if (axes == RotationAxis.MouseX)
{
transform.Rotate(0, Input.GetAxis("Mouse X") * sensHorizontal, 0);
}
else if (axes == RotationAxis.MouseY)
{
_rotationX -= Input.GetAxis("Mouse Y") * sensVertical;
_rotationX = Mathf.Clamp(_rotationX, minimumVert, maximumVert); //Clamps the vertical angle within the min and max limits (45 degrees)
float rotationY = transform.localEulerAngles.y;
transform.localEulerAngles = new Vector3(_rotationX, rotationY, 0);
}
}
}
You could store the rotation in a field and thus making sure the only thing changing it is your script:
move it to LateUpdate in order for it to be the last thing called in a frame (also see Order of Execution for Event Functions)
float xRotation;
float yRotation;
void Start()
{
xRotation = transform.localEulerAngles.x;
yRotation = transform.localEulerAngles.y;
}
void LateUpdate()
{
if (axes == RotationAxis.MouseX)
{
yRotation += Input.GetAxis("Mouse X") * sensHorizontal;
}
else if (axes == RotationAxis.MouseY)
{
xRotation -= Input.GetAxis("Mouse Y") * sensVertical;
//Clamps the vertical angle within the min and max limits (45 degrees)
xRotation= Mathf.Clamp(lastXRotation , minimumVert, maximumVert);
}
// always overwrite with fixed values instead of using transform.rotation based ones
transform.localRotation = Quaternion.Euler(xRotation, yRotation, 0);
}
just to be sure you could also additionally but it to FixedUpdate in order to also reset changes from the Physics. If there is any RigidBody in play this should be the way to go anyway but then not using the Transform but rather the Rigidbody component.
void FixedUpdate()
{
transform.localRotation = Quaternion.Euler(xRotation, yRotation, 0);
}
Note however: As you currently have it setup you will get unexpected rotations. Rotating around the two axis here has the problem of also rotating along the local coordinate system.
In general you should rather have a parent object for the Y rotation and only do the X rotation on the object itself.

How do i make my character move in the direction of the camera (Unity)

In Unity I want to make it so that when I hold w, instead of going in a single direction I want it to go forward in the direction of my camera how do I do that? (Sorry I'm new to unity)
EDIT: The movement script is:
using UnityEngine;
using System.Collections;
public class Player_Movement : MonoBehaviour {
public float speed = 6.0F;
public float jumpSpeed = 8.0F;
public float gravity = 20.0F;
private Vector3 moveDirection = Vector3.zero;
void Update() {
CharacterController controller = GetComponent<CharacterController>();
if (controller.isGrounded) {
moveDirection = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
moveDirection = transform.TransformDirection(moveDirection);
moveDirection *= speed;
if (Input.GetButton("Jump"))
moveDirection.y = jumpSpeed;
}
moveDirection.y -= gravity * Time.deltaTime;
controller.Move(moveDirection * Time.deltaTime);
}
}
As indicated by #lockstock, the direction the camera is facing can be retrieved from its transform. Here is an example below if you want to know how to use it.
public class Player_Movement : MonoBehaviour
{
public float speed = 6.0F;
public float jumpSpeed = 8.0F;
public float gravity = 20.0F;
// Drag & Drop the camera in this field, in the inspector
public Transform cameraTransform ;
private Vector3 moveDirection = Vector3.zero;
void Update() {
CharacterController controller = GetComponent<CharacterController>();
if (controller.isGrounded) {
moveDirection = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
moveDirection = cameraTransform.TransformDirection(moveDirection);
moveDirection *= speed;
if (Input.GetButton("Jump"))
moveDirection.y = jumpSpeed;
}
moveDirection.y -= gravity * Time.deltaTime;
controller.Move(moveDirection * Time.deltaTime);
}
}
This scripts works without any error. I've tested it in Unity myself.
The forward direction of the camera is obtained by using Camera.main.transform.forward
turn your player so the blue axis is facing the same direction as the blue axis on the camera. then drag and drop the camera onto the player. now when you move the player, the camera will follow, and stay behind the player