- Home /
The question is answered, right answer was accepted
transform.eulerAngles Flipping a character
Hi, I've been learning about this script for a few days, and I ran into something that is kind of confusing. It has to do with this line right here.
// Face Direction
float moveDir = Input.GetAxisRaw("Horizontal");
if (moveDir !=0) {
transform.eulerAngles = (moveDir>0)?Vector3.up * 180:Vector3.zero;
}
I notice that if I set the Input to positive 1 then the character I am using has its rotation flipped i.e. if transform.eulerAngles = moveDir>0 then flip the character on the y axis 180 degrees, otherwise don't do anything/keep the vector at zero.
But it still works if I turn the other way (if the moveDir is less than zero), even if I didn't actual put any code in to tell it to. So am I missing something. Is this just the way the code works or transform.eulerAngles works?
using UnityEngine;
using System.Collections;
[RequireComponent(typeof(PlayerPhysics))]
public class PlayerController : MonoBehaviour {
// Player Handling
public float gravity = 20;
public float walkSpeed = 8;
public float runSpeed = 12;
public float acceleration = 30;
public float jumpHeight = 12;
private float animationSpeed;
private float currentSpeed;
private float targetSpeed;
private Vector2 amountToMove;
private PlayerPhysics playerPhysics;
private Animator animator;
void Start () {
playerPhysics = GetComponent<PlayerPhysics>();
animator = GetComponent<Animator>();
}
void Update () {
// Reset acceleration upon collision
if (playerPhysics.movementStopped) {
targetSpeed = 0;
currentSpeed = 0;
}
// If player is touching the ground
if (playerPhysics.grounded) {
amountToMove.y = 0;
// Jump
if (Input.GetButtonDown("Jump")) {
amountToMove.y = jumpHeight;
}
}
// Set animator parameters
animationSpeed = IncrementTowards(animationSpeed,Mathf.Abs(targetSpeed),acceleration);
animator.SetFloat("Speed",animationSpeed);
// Input
float speed = (Input.GetButton("Run"))?runSpeed:walkSpeed;
targetSpeed = Input.GetAxisRaw("Horizontal") * speed;
currentSpeed = IncrementTowards(currentSpeed, targetSpeed,acceleration);
// Set amount to move
amountToMove.x = currentSpeed;
amountToMove.y -= gravity * Time.deltaTime;
playerPhysics.Move(amountToMove * Time.deltaTime);
// Face Direction
float moveDir = Input.GetAxisRaw("Horizontal");
if (moveDir !=0) {
transform.eulerAngles = (moveDir>0)?Vector3.up * 180:Vector3.zero;
}
}
// Increase n towards target by speed
private float IncrementTowards(float n, float target, float a) {
if (n == target) {
return n;
}
else {
float dir = Mathf.Sign(target - n); // must n be increased or decreased to get closer to target
n += a * Time.deltaTime * dir;
return (dir == Mathf.Sign(target-n))? n: target; // if n has now passed target then return target, otherwise return n
}
}
}
&&
using UnityEngine;
using System.Collections;
[RequireComponent (typeof(BoxCollider))]
public class PlayerPhysics : MonoBehaviour {
public LayerMask collisionMask;
private BoxCollider collider;
private Vector3 s;
private Vector3 c;
private Vector3 originalSize;
private Vector3 originalCentre;
private float colliderScale;
private int collisionDivisionsX = 3;
private int collisionDivisionsY =10;
private float skin = .005f;
[HideInInspector]
public bool grounded;
[HideInInspector]
public bool movementStopped;
Ray ray;
RaycastHit hit;
void Start() {
collider = GetComponent<BoxCollider>();
colliderScale = transform.localScale.x;
originalSize = collider.size;
originalCentre = collider.center;
SetCollider(originalSize,originalCentre);
}
public void Move(Vector2 moveAmount) {
float deltaY = moveAmount.y;
float deltaX = moveAmount.x;
Vector2 p = transform.position;
// Check collisions above and below
grounded = false;
for (int i = 0; i<collisionDivisionsX; i ++) {
float dir = Mathf.Sign(deltaY);
float x = (p.x + c.x - s.x/2) + s.x/(collisionDivisionsX-1) * i; // Left, centre and then rightmost point of collider
float y = p.y + c.y + s.y/2 * dir; // Bottom of collider
ray = new Ray(new Vector2(x,y), new Vector2(0,dir));
Debug.DrawRay(ray.origin,ray.direction);
if (Physics.Raycast(ray,out hit,Mathf.Abs(deltaY) + skin,collisionMask)) {
// Get Distance between player and ground
float dst = Vector3.Distance (ray.origin, hit.point);
// Stop player's downwards movement after coming within skin width of a collider
if (dst > skin) {
deltaY = dst * dir - skin * dir;
}
else {
deltaY = 0;
}
grounded = true;
break;
}
}
// Check collisions left and right
movementStopped = false;
for (int i = 0; i<collisionDivisionsY; i ++) {
float dir = Mathf.Sign(deltaX);
float x = p.x + c.x + s.x/2 * dir;
float y = p.y + c.y - s.y/2 + s.y/(collisionDivisionsY-1) * i;
ray = new Ray(new Vector2(x,y), new Vector2(dir,0));
Debug.DrawRay(ray.origin,ray.direction);
if (Physics.Raycast(ray,out hit,Mathf.Abs(deltaX) + skin,collisionMask)) {
// Get Distance between player and ground
float dst = Vector3.Distance (ray.origin, hit.point);
// Stop player's downwards movement after coming within skin width of a collider
if (dst > skin) {
deltaX = dst * dir - skin * dir;
}
else {
deltaX = 0;
}
movementStopped = true;
break;
}
}
if (!grounded && !movementStopped) {
Vector3 playerDir = new Vector3(deltaX,deltaY);
Vector3 o = new Vector3(p.x + c.x + s.x/2 * Mathf.Sign(deltaX),p.y + c.y + s.y/2 * Mathf.Sign(deltaY));
ray = new Ray(o,playerDir.normalized);
if (Physics.Raycast(ray,Mathf.Sqrt(deltaX * deltaX + deltaY * deltaY),collisionMask)) {
grounded = true;
deltaY = 0;
}
}
Vector2 finalTransform = new Vector2(deltaX,deltaY);
transform.Translate(finalTransform,Space.World);
}
// Set collider
public void SetCollider(Vector3 size, Vector3 centre) {
collider.size = size;
collider.center = centre;
s = size * colliderScale;
c = centre * colliderScale;
}
}
"otherwise don't do anything/keep the vector at zero"
Actually, it's "otherwise set the vector to zero" - so if it was 180 (flipped), then it becomes zero (not flipped).
Does that explain how this line handles both the positive and negative cases?
Answer by LMan · Jun 10, 2014 at 12:31 AM
Well the way that particular line there works is by way of something called a "Ternary Operator"- it's that "?" you see there.
It grabs the Horizontal input and saves it in that moveDir variable. That number is going to be between 1 and -1, 1 being the positive x direction or right.
Then it says "If the input value is NOT zero, do this!"
And inside the if statement you see that the EulerAngles are being written to, and then it's followed by that Ternary operation- where it checks a statement (moveDir>0, in this case.) for true or false. if it's true, it will use the value that comes next- "Vector3.up * 180" if it's false, it uses the value that comes after the ":", which is the value Vector3.zero.
So to recap the Ternary, it checks if moveDir is more than 0 (heading right) and if so, it sets the eulerAngles value to (0, 180, 0). if not, then it sets it to (0,0,0).
ok just got it. thanks very much. kind of a herp derp moment right there.