Unity 3D Door Script Angle Transformation - c#

i write the following code for open and close doors:
using UnityEngine;
using System.Collections;
public class LittleDoorScript : MonoBehaviour
{
private bool doorOpen = false;
private Ray ray;
private RaycastHit hit;
private float distance = 5.0f;
public GameObject door;
private void Update()
{
if (Input.GetKeyDown("e"))
{
ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out hit, distance))
{
if(hit.collider.gameObject.name == door.name)
{
if (!doorOpen)
{
Quaternion targetRotation = Quaternion.Euler(0.0f, 90.0f, 0.0f);
hit.transform.localRotation = Quaternion.Slerp(transform.localRotation, targetRotation, 2.0f);
doorOpen = true;
}
else
{
Quaternion targetRotation2 = Quaternion.Euler(0.0f, 0.0f, 0.0f);
hit.transform.localRotation = Quaternion.Slerp(transform.localRotation, targetRotation2, 2.0f);
doorOpen = false;
}
}
}
}
}
}
the problem is the door not open in the right angle and if i close the door the not go back in the start position.
Maybe somebosy have an idea?

Try changing the angle to -90, it always happens to me.
Quaternion targetRotation = Quaternion.Euler(0.0f, -90.0f, 0.0f);
the second one:
Quaternion targetRotation2 = Quaternion.Euler(0.0f, 90.0f, 0.0f);

Related

How to Rotate 2D Sprite Towards Moving Direction?

I have been searching all day and reading forums but I can't find a way that works. I'm making a top-down view horror game. When my player walks normally he can look around with the cursor in any direction, but when he wants to run he switches to "tank" controls and rotates toward the running direction. I need something like this.
My player movement script so far:
public float walkSpeed;
public float runSpeed;
public float turnSpeed;
private Rigidbody2D rb;
public Camera cam;
private Vector2 moveDirection;
void Start()
{
rb = GetComponent<Rigidbody2D>();
}
void Update()
{
ProcessInput();
}
void FixedUpdate()
{
Move();
}
private void ProcessInput()
{
float moveX = Input.GetAxisRaw("Horizontal");
float moveY = Input.GetAxisRaw("Vertical");
moveDirection = new Vector2(moveX, moveY).normalized;
}
void Move()
{
if (Input.GetKey(KeyCode.LeftShift))
{
//Looking toward movement direction should be applied here
} else {
rb.velocity = new Vector2(moveDirection.x * walkSpeed, moveDirection.y * walkSpeed);
Vector3 mousePosition = cam.ScreenToWorldPoint(Input.mousePosition);
Vector2 direction = mousePosition - transform.position;
float angle = Vector2.SignedAngle(Vector2.right, direction) - 90f;
Vector3 targetRotation = new Vector3(0, 0, angle);
transform.rotation = Quaternion.RotateTowards(transform.rotation, Quaternion.Euler(targetRotation), turnSpeed * Time.deltaTime);
}
}
Any help is greatly appreciated! Thanks in advance!
This problem can be solved by substituting moveDirection instead of the mouse look direction, here it is enough to define a hypothetical variable called direction to detect the correct direction in each of these conditions.
var direction = new Vector2();
var currentSpeed = walkSpeed;
if (Input.GetKey(KeyCode.LeftShift))
{
direction = moveDirection;
currentSpeed = runSpeed;
} else {
direction = cam.ScreenToWorldPoint(Input.mousePosition) - transform.position;
}
var angle = Vector2.SignedAngle(Vector2.right, direction) - 90f;
var targetRotation = new Vector3(0, 0, angle);
var lookTo = Quaternion.Euler(targetRotation);
rb.velocity = new Vector2(moveDirection.x, moveDirection.y) * runSpeed *Time.deltaTime;
transform.rotation = Quaternion.RotateTowards(transform.rotation, lookTo , turnSpeed * Time.deltaTime);

How can I clamp the rotation to 180 degrees each side or to set on my own clamp degrees when rotating the player head?

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Interactable : MonoBehaviour
{
public Transform objToRotateLookAT;
public Transform body;
public float lookAtSpeed;
public float originalLookSpeed;
public float rotationSpeed;
public float distanceToInteract;
public Animator anim;
public GameObject text;
private bool raycastSucceed;
private Vector3 originalRotation;
private bool originalRotFlag = true;
private bool isInstant = false;
// Start is called before the first frame update
void Start()
{
Cursor.visible = false;
originalRotation = objToRotateLookAT.position;
if (anim == null)
{
anim = GetComponent<Animator>();
}
}
void FixedUpdate()
{
int layerMask = 1 << 8;
RaycastHit hit;
// Does the ray intersect any objects excluding the player layer
if (Physics.Raycast(transform.position, transform.TransformDirection(Vector3.forward), out hit, Mathf.Infinity, layerMask))
{
if (!raycastSucceed)
Debug.Log("Did Hit");
raycastSucceed = true;
Debug.DrawRay(transform.position, transform.TransformDirection(Vector3.forward) * hit.distance, Color.red);
text.SetActive(true);
if (Vector3.Distance(transform.position, hit.transform.position) <= distanceToInteract)
{
anim.SetBool("Pickup Item", true);
}
}
else
{
if (raycastSucceed)
Debug.Log("Did not Hit");
raycastSucceed = false;
Debug.DrawRay(transform.position, transform.TransformDirection(Vector3.forward) * 1000, Color.yellow);
text.SetActive(false);
if (originalRotFlag == false)
{
}
else
{
}
}
}
private void Update()
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
Quaternion targetRotation = Quaternion.LookRotation(ray.direction);
if (isInstant)
{
objToRotateLookAT.rotation = targetRotation;
}
else
{
Quaternion currentRotation = objToRotateLookAT.rotation;
float angularDifference = Quaternion.Angle(currentRotation, targetRotation);
// will always be positive (or zero)
if (angularDifference > 0) objToRotateLookAT.rotation = Quaternion.Slerp(
currentRotation,
targetRotation,
(rotationSpeed * 180 * Time.deltaTime) / angularDifference
);
else objToRotateLookAT.rotation = targetRotation;
}
}
}
In the Update I'm using the mouse cursor position to rotate the layer head.
The problem is that I can rotate the head to the back so in some cases the body stay facing forward while the head is facing backward.
I want to make some clamp so the head will be able to rotate to the sides and up more or less like a real human head rotation limits.
I just not sure how and where to make the clamp in the Update.
Screenshot when running the game the head and body are fine facing same direction :
Same direction
but then if I'm moving the mouse too much and rotating the head then :
The head is facing backward and the body forward.
I tried this but it's not working nothing changed tried to test a clamp on both targetRotation and currentRotation to limit it to -9 and 9 but nothing changed :
private void Update()
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
Quaternion targetRotation = Quaternion.LookRotation(ray.direction);
if (isInstant)
{
objToRotateLookAT.rotation = targetRotation;
}
else
{
Quaternion currentRotation = objToRotateLookAT.rotation;
targetRotation.y = Mathf.Clamp(targetRotation.y, -9f, 9f);
targetRotation.x = Mathf.Clamp(targetRotation.x, -9f, 9f);
targetRotation.z = Mathf.Clamp(targetRotation.z, -9f, 9f);
currentRotation.y = Mathf.Clamp(currentRotation.y, -9f, 9f);
currentRotation.x = Mathf.Clamp(currentRotation.x, -9f, 9f);
currentRotation.z = Mathf.Clamp(currentRotation.z, -9f, 9f);
float angularDifference = Quaternion.Angle(currentRotation, targetRotation);
// will always be positive (or zero)
if (angularDifference > 0) objToRotateLookAT.rotation = Quaternion.Slerp(
currentRotation,
targetRotation,
(rotationSpeed * 180 * Time.deltaTime) / angularDifference
);
else objToRotateLookAT.rotation = targetRotation;
}
}
Here is a link for a short video clip I recorded showing the problem when the cube is behind the player and that the player head rotation speed is not the same speed as the cube so in most of the time the player is not looking at the cube but looking at it in general direction :
https://www.youtube.com/watch?v=gApXlKv7hKY&feature=youtu.be

How can I move the object back to it's start position if the raycast is not hitting?

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class OnMouseOverEvent : MonoBehaviour
{
public float duration;
public string tag;
public Vector3 startPos;
public Vector3 endPos;
public float distancetoMove = 1f;
public float lerpTime = 5;
private float currentLerpTime = 0;
private void Start()
{
startPos = transform.position;
endPos = transform.position - Vector3.forward * distancetoMove;
}
private void Update()
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit, 100))
{
if (hit.transform.tag == tag)
{
currentLerpTime += Time.deltaTime;
if(currentLerpTime >= lerpTime)
{
currentLerpTime = lerpTime;
}
float Perc = currentLerpTime / lerpTime;
transform.position = Vector3.Lerp(startPos, endPos, Perc);
}
else
{
transform.position = Vector3.Lerp(endPos, startPos, Perc);
}
}
}
}
If it's hitting the object is moving smooth slowly forward but I want that while the raycast keep hitting the object it will move forward and if got to the distance keep it stay there as long as the raycast hitting it.
But once moving the mouse and the raycast is not hitting the object either in the middle of the movement or when it got to the distance move the object back to it's start position.
So when moving the mouse out of the object area it will start moving either forward to endPos or backward to startPos.
Another way to do it: (Without Raycast)
using UnityEngine;
public class Move : MonoBehaviour
{
public float speed = 5f;
public float distancetoMove = 1f;
public bool goForward;
public Vector3 startPos;
public Vector3 endPos;
private void Start()
{
startPos = transform.position;
endPos = transform.position - Vector3.forward * distancetoMove;
}
void Update()
{
if (goForward)
{
transform.position = Vector3.MoveTowards(transform.position, endPos, speed * Time.deltaTime);
}
else
{
transform.position = Vector3.MoveTowards(transform.position, startPos, speed * Time.deltaTime);
}
}
private void OnMouseOver()
{
goForward = true;
}
private void OnMouseExit()
{
goForward = false;
}
}
you have to declare Perc outsdide if if you want to use ot inside else
to solve your problem
change:
inside if (hit.transform.tag == tag)
transform.position = Vector3.Lerp(start, endPos, Perc);
to this:
transform.position = Vector3.Lerp(transform.position, endPos, Perc);
and inside else
else{
transform.position = Vector3.Lerp(endPos, startPos, Perc);
}
to this:
else{
transform.position = Vector3.Lerp(transform.position, startPos, Perc);
}
your code will become like this:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class OnMouseOverEvent : MonoBehaviour
{
public float duration;
public string tag;
public Vector3 startPos;
public Vector3 endPos;
public float distancetoMove = 1f;
public float lerpTime = 5;
float Perc;
private float currentLerpTime = 0;
private void Start()
{
startPos = transform.position;
endPos = transform.position - Vector3.forward * distancetoMove;
}
private void Update()
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit, 100))
{
if (hit.transform.tag == tag)
{
currentLerpTime += Time.deltaTime;
if (currentLerpTime >= lerpTime)
{
currentLerpTime = lerpTime;
}
Perc = currentLerpTime / lerpTime;
transform.position = Vector3.Lerp(transform.position, endPos, Perc);
}
else
{
transform.position = Vector3.Lerp(transform.position, startPos, Perc);
}
}
}
}
Interpolant (Perc) not updating properly
Your object currently moves in the update by a Lerp, which the interpolant is Perc.
The problem is that your code for updating your Perc by lerp timer is only done when the raycast hits this object.
You can update your Perc by lerp-timer before/after you done the movement process, like so:
private float Perc;
private void Update()
{
GetPercByLerpTime(); // Update before it moves
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit, 100))
{
if (hit.transform.tag == tag)
{
transform.position = Vector3.Lerp(startPos, endPos, Perc);
}
else
{
transform.position = Vector3.Lerp(endPos, startPos, Perc);
}
}
// Or you can update your 'Perc' here.
}
private void UpdatePercByLerpTime(){
currentLerpTime += Time.deltaTime;
if(currentLerpTime >= lerpTime)
{
currentLerpTime = lerpTime;
}
Perc = currentLerpTime / lerpTime;
}
Note: You might notice that currentLerpTime will keep incrementing until it reaches lerpTime, and it will stay as the same value as lerpTime.
You might want to implement something that either decreases or resets currentLerpTime.
No movement occurs if raycast hits nothing.
Your currently code only moves the object if the raycast hits something. (Though it does move in the correct direction depending if it hit this object)
What you probably want is to move the object back to the start position if the raycast hit nothing or the raycast hit something else.
So your final result would look like this:
private float Perc;
private void Update() {
UpdatePercByLerpTime();
if (MouseRaycastHitThisObject()) {
transform.position = Vector3.Lerp(startPos, endPos, Perc);
} else {
transform.position = Vector3.Lerp(endPos, startPos, Perc);
}
// Or you can update your 'Perc' here.
}
// True if the raycastfrom the mouse position hits this object
private bool MouseRaycastHitThisObject(){
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit, 100)) {
return hit.transform.tag == tag;
}
// Raycast did not hit anything; Player's mouse is not hovering over anything.
return false;
}
private void UpdatePercByLerpTime(){
currentLerpTime += Time.deltaTime;
if(currentLerpTime >= lerpTime) {
currentLerpTime = lerpTime;
}
Perc = currentLerpTime / lerpTime;
}

Raycasting Unity/ gravity Error

I'm using the Charactercontroller component for the movement of my character.
The thing I'm trying to achieve is for the character to go when I'm clicking with the mouse. For that, I'm rotating where I click and then going forward to the point where the ray collider with my terrain.
The character does move and goes to the point I want.
The problem is when walking into a ramp, for example, the character keeps walking in the air and does not go down (gravity problem as far as I can understand although when I test putting the character in the air when the editor it does go down) it stops above when it supposed to go and starts spinning really fast.
Here's my movement script
private float gravity = 1f;
Animator anim;
CharacterController charController;
private float mvtSpeed = 3f;
private float distanceToPoint;
Vector3 playerMvt;
bool canMove = false;
CollisionFlags collisionFlags;
Ray ray;
RaycastHit hit;
Vector3 PlayerTarget;
float height;
private void Awake()
{
anim = GetComponent<Animator>();
charController = GetComponent<CharacterController>();
}
void MoveThePlayer()
{
if (Input.GetMouseButton(0))
{
ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out hit)) {
if (hit.collider is TerrainCollider)
{
if (Vector3.Distance(transform.position, hit.point) >= 0.5f)
{
canMove = true;
anim.SetFloat("Walk", 1.0f);
PlayerTarget = hit.point;
}
}//terrain collider
}//raycast
}//mouse Down
if (canMove)
{
Vector3 targetTemp = new Vector3(PlayerTarget.x, transform.position.y, PlayerTarget.z);
transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(targetTemp - transform.position), 15.0f * Time.deltaTime);
playerMvt = transform.forward * mvtSpeed * Time.deltaTime;
if (Vector3.Distance(transform.position, PlayerTarget) <= 0.1f)
{
anim.SetFloat("Walk", 0f);
playerMvt.Set(0f, 0f, 0f);
}
}//canMove
}
private void Update()
{
MoveThePlayer();
charController.Move(playerMvt);
if (!charController.isGrounded)
{
playerMvt.y -= gravity * Time.deltaTime;
}
}
A few things.
canMove is never reset to false, it should probably reset in here
if (Vector3.Distance(transform.position, PlayerTarget) <= 0.1f)
{
anim.SetFloat("Walk", 0f);
playerMvt.Set(0f, 0f, 0f);
}
This code has no impact where its located right now:
if (!charController.isGrounded)
{
playerMvt.y -= gravity * Time.deltaTime;
}
You apply gravity to playerMvt.y after you have already moved the player, and the next frame you will re-assign playerMvt here:
playerMvt = transform.forward * mvtSpeed * Time.deltaTime;
So change it up to this
private void Update()
{
MoveThePlayer();
if (!charController.isGrounded)
{
playerMvt.y -= gravity * Time.deltaTime;
}
charController.Move(playerMvt);
}

Debug character movement backwards in Unity 5

I have a character(robot Kyle) and I can move the character from side to side, and forwards. When the character begins to move backwards it disappears for no reason.
Also, how would I move the character in the direction of the mouse? I have it so it faces in direction of the mouse, but the camera angle distorts that a little bit.
using UnityEngine;
using System.Collections;
public class PlayerScript : MonoBehaviour {
public GameControlScript control;
float strafeSpeed = 2;
Animator anim;
bool jumping = false;
void Start () {
anim = GetComponent<Animator>();
}
void Update () {
if (Input.GetKey(KeyCode.RightArrow)){
Vector3 newPosition = this.transform.position;
newPosition.x++;
this.transform.position = newPosition;
}
if (Input.GetKey(KeyCode.LeftArrow)){
Vector3 newPosition = this.transform.position;
newPosition.x--;
this.transform.position = newPosition;
}
if (Input.GetKey(KeyCode.UpArrow)){
Vector3 newPosition = this.transform.position;
newPosition.z++;
this.transform.position = newPosition;
}
if (Input.GetKey(KeyCode.DownArrow)){
Vector3 newPosition = this.transform.position;
newPosition.z--;
this.transform.position -= newPosition;
}
Vector3 mousePos = new Vector3(Input.mousePosition.x, Input.mousePosition.y, 1000);
Vector3 lookPos = Camera.main.ScreenToWorldPoint(mousePos);
lookPos = lookPos - this.transform.position;
float angle = Mathf.Atan2(lookPos.z, lookPos.x) * Mathf.Rad2Deg;
this.transform.rotation = Quaternion.AngleAxis(angle, Vector3.down);
}
void OnTriggerEnter(Collider other)
{
if(other.gameObject.name == "Powerup(Clone)")
{
control.PowerupCollected();
}
else if(other.gameObject.name == "Obstacle(Clone)" &&
jumping == false)
{
control.SlowWorldDown();
}
Destroy(other.gameObject);
}
}
ScreenToWorldPoint may be your problem because you are fixing 1000 as the distance between the camera and your object.
Checkout out this link and try to log your lookPos variable.

Categories