How to prevent bouncing off the wall when moving against it? - c#

My problem is, that when Im moving against a wall, that there is a little bouncing effect. Here is a video of it:
https://www.dropbox.com/s/t5drxu4aw60nq59/meem.mp4?dl=0
I dont know how to fix it, I already tried everything. I hope someone know a solution for this. Thank you
Here is the movement script:
public class PlayerMovement : MonoBehaviour
{
public float speed;
public float x;
public float y;
public bool canMove;
void FixedUpdate()
{
if (canMove)
{
if (Input.GetKey(KeyCode.UpArrow) || Input.GetKey(KeyCode.W))
{
GoUp();
}
else if (Input.GetKey(KeyCode.DownArrow) || Input.GetKey(KeyCode.S))
{
GoDown();
}
else if (Input.GetKey(KeyCode.RightArrow) || Input.GetKey(KeyCode.D))
{
GoRight();
}
else if (Input.GetKey(KeyCode.LeftArrow) || Input.GetKey(KeyCode.A))
{
GoLeft();
}
if (Input.GetKey(KeyCode.UpArrow) && Input.GetKey(KeyCode.RightArrow))
{
GoUp();
GoRight();
}
else if (Input.GetKey(KeyCode.UpArrow) && Input.GetKey(KeyCode.LeftArrow))
{
GoUp();
GoLeft();
}
else if (Input.GetKey(KeyCode.DownArrow) && Input.GetKey(KeyCode.RightArrow))
{
GoDown();
GoRight();
}
else if (Input.GetKey(KeyCode.DownArrow) && Input.GetKey(KeyCode.LeftArrow))
{
GoDown();
GoLeft();
}
this.transform.position = new Vector2(this.transform.position.x + x, this.transform.position.y + y);
x = 0;
y = 0;
}
}
public void GoUp()
{
y = Time.deltaTime * speed;
}
public void GoDown()
{
y = Time.deltaTime * (-speed);
}
public void GoRight()
{
x = Time.deltaTime * speed;
}
public void GoLeft()
{
x = Time.deltaTime * (-speed);
}
}

Find two suggestions to handle stop going right example. Note they are going to be not debugued code, as I dont know your project details. Also no the most correct in many aspects for the saem reason. Just to give you the idea.
1.- With distance control
public GameObject wall; //ref to wall set in editor
float playerHalfSize = 0f;
float wallHalfSize = 0f;
float bodiesTotDist = 0f;
Start() {
playerHalfSize = transform.scale.x / 2;
wallHalfSize = wall.scale.x / 2; // supposing size is set with scale. Preferably get the size with a collider or the mesh renderer Bounds class inside the respective collider or MeshRenderer classes
bodiesTotDist = playerHalfSize + wallHalfSize;
}
float getDistanceToWall(wall) {
float distance = Vector3.Distance(transform.position, wall.transform.position) - bodiesTotDist;
}
public void GoRight()
{
if (getDistanceToWall() > 0) //this avoids your player x move further to the right
x = Time.deltaTime * speed;
}
If you might still see the bouncing you can try to adjust manually a threshold distance, for example getDistanceToWall() > 0.5f or adjunting the collider.
2.- With a trigger: If you put a trigger a little bit bigger that your wall, when the wall touches the player you can handle in the code also to avoid further x right set.
bool isRightWallTouching = false;
void OnTriggerEnter2D(Collider2D col)
{
if (col.gameObject == wall) //for the right wall
isRightWallTouching = true;
}
void OnTriggerExit2D(Collider2D other)
{
isRightWallTouching = false;
}
public void GoRight()
{
if (isRightWallTouching > 0) //this avoids your player x move further to the right
x = Time.deltaTime * speed;
}
As told, not debugged code so might have some failures and the chance that you might have many walls, so this suggestion may lead to a lots of bools dirty solution, but hope it can provide you some inspiration to put your game to work and move on :)

Related

Unity Top Down Game Movement help needed

I just started coding 3 days ago and in my game I only want 4 movement-directions instead of 8.
I have a fully working code with animations and walking logic, but I am to nooby make a Code by my own, because I just started.
So could someone modify my code, so that I can only go in 4-directions.
Thank you :)
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
private Animator anim;
private float x, y;
private bool isWalking;
public float moveSpeed;
void Start()
{
anim = GetComponent<Animator>();
}
void Update()
{
x = Input.GetAxis("Horizontal");
y = Input.GetAxis("Vertical");
if (x != 0 || y != 0)
{
if (!isWalking)
{
isWalking = true;
anim.SetBool("isWalking", isWalking);
}
Move();
}
else
{
if (isWalking)
{
isWalking = false;
anim.SetBool("isWalking", isWalking);
}
}
}
private void Move()
{
anim.SetFloat("X", x);
anim.SetFloat("Y", y);
transform.Translate(x * Time.deltaTime * moveSpeed,
y * Time.deltaTime * moveSpeed,
0);
}
}
I wrote 2 different (but fairly similar) options for moving in just 4 directions.
First option, just pick which axis has the highest value and move that direction (if using a controller, this may or may not be work the way you want).
Second and simpler option, keep moving the player on its current axis regardless if another axis has a higher value.
Both code options are there and you can play around with either option. Hopefully this helps start you on which path you want to take.
public class PlayerMovement : MonoBehaviour {
private Animator anim;
private float x, y;
private bool isWalking;
private bool movingX = false;
public float moveSpeed;
void Start() {
anim = GetComponent<Animator>();
}
void Update() {
x = Input.GetAxis("Horizontal");
y = Input.GetAxis("Vertical");
if (x != 0 || y != 0) {
if (!isWalking) {
isWalking = true;
anim.SetBool("isWalking", isWalking);
}
Move();
} else {
if (isWalking) {
isWalking = false;
anim.SetBool("isWalking", isWalking);
}
}
}
private void Move() {
// whichever direction has the highest value, will be the direction we go.
///*
if (Mathf.Abs(x) > Mathf.Abs(y)) {
movingX = true;
y = 0;
} else if (Mathf.Abs(x) < Mathf.Abs(y)) {
movingX = false;
x = 0;
} else {
// keeps going same direction if both maxed.
if (movingX) {
y = 0;
} else {
x = 0;
}
}
//*/
// or simple, just keep going in same direction until player stops using axis.
/*
if (x != 0 && y == 0) {
movingX = true;
} else if (x == 0 && y != 0) {
movingX = false;
}
if (movingX) {
y = 0;
} else {
x = 0;
}
*/
anim.SetFloat("X", x);
anim.SetFloat("Y", y);
transform.Translate(x * Time.deltaTime * moveSpeed,
y * Time.deltaTime * moveSpeed,
0);
}
}
Use XOR operator.
if (x != 0 ^ y != 0)
{
// moving..
}

rayHit.point Instantiates at 0 0 0 Unity

I made a Gun Script (using YT videos) and a Bullethole GameObject should Instantiate at the Position the RayCast hits an Object. But it is always at 0 0 0. I tried many thing but non work.
GameObject bulletHoleClone = Instantiate(bulletHole, rayHit.point, Quaternion.Euler(0, 180, 0));
Destroy(bulletHoleClone, bulletHoleTime);
Whole Code:
using TMPro;
using UnityEngine;
public class GunScript : MonoBehaviour
{
//Gun Stats
public int damage;
public float timeBetweenShooting, spread, range, reloadTime, timeBetweenShots;
public int magazineSize, bulletsPerTap;
public bool allowHoldButton;
int bulletsLeft, bulletsShot;
private float normalSpread;
//bools
bool shooting, readyToShoot, reloading;
//Graphics
public CameraShake camShake;
public float camShakeStrengh, camShakeDuration;
public GameObject muzzleFlash, bulletHole;
public TextMeshProUGUI text;
public float muzzleFlashTime = 0.1f; //Will be deleted after there is an actual Effect and not a Box
public float bulletHoleTime = 3f;
//Refrences
public Camera fpsCam;
public Transform attackPoint;
private RaycastHit rayHit;
public LayerMask dafuqIsEnemey;
private Rigidbody rb;
private void Awake()
{
rb = GetComponent<Rigidbody>();
bulletsLeft = magazineSize;
readyToShoot = true;
normalSpread = spread;
}
private void Update()
{
MyInput();
//Set Text to BulletAmount
text.SetText(bulletsLeft + " / " + magazineSize);
}
private void MyInput()
{
if (allowHoldButton) shooting = Input.GetKey(KeyCode.Mouse0);
else shooting = Input.GetKeyDown(KeyCode.Mouse0);
if (Input.GetKeyDown(KeyCode.R) && bulletsLeft < magazineSize && !reloading) Reload();
//PewPew
if (readyToShoot && shooting && !reloading && bulletsLeft > 0)
{
bulletsShot = bulletsPerTap;
Shoot();
}
if (rb.velocity.magnitude > 0)
spread = normalSpread * 1.5f;
else spread = normalSpread;
if (Input.GetKey(KeyCode.LeftControl))
spread = normalSpread * 2f;
else spread = normalSpread;
}
private void Shoot()
{
readyToShoot = false;
//Bullets go BRRRRRRRRRR
float x = Random.Range(-spread, spread);
float y = Random.Range(-spread, spread);
//Calculate Direction with Spread
Vector3 direction = fpsCam.transform.forward + new Vector3(x, y, 0);
//Maybe Add that the Ray Isnt coming out of your Head. Instead make it apear on the GunTip
if (Physics.Raycast(fpsCam.transform.position, direction, out rayHit, range, dafuqIsEnemey))
{
Debug.Log(rayHit.collider.name);
if (rayHit.collider.CompareTag("Enemy"))
{
Debug.Log("Hit An Enemy");
//rayHit.collider.GetComponent<ShootingAi>().TakeDamage(damage);
}
}
//Shake Camera
camShake.Shake(camShakeDuration, camShakeStrengh);
//Graphics
GameObject bulletHoleClone = Instantiate(bulletHole, rayHit.point, Quaternion.Euler(0, 180, 0));
GameObject muzzleClone = Instantiate(muzzleFlash, attackPoint.position, Quaternion.identity);
Destroy(muzzleClone, muzzleFlashTime);
Destroy(bulletHoleClone, bulletHoleTime);
Debug.Log(rayHit.point);
bulletsLeft--;
bulletsShot--;
Invoke("ResetShot", timeBetweenShooting);
if (bulletsShot > 0 && bulletsLeft > 0)
Invoke("Shoot", timeBetweenShooting);
}
private void ResetShot()
{
readyToShoot = true;
}
private void Reload()
{
reloading = true;
Invoke("ReloadFinished", reloadTime);
}
private void ReloadFinished()
{
bulletsLeft = magazineSize;
reloading = false;
}
}
You're not hitting anything. You check to see if you hit something, and then spawn a bullet hole even if you didn't hit anything.
If you didn't hit anything, there isn't anywhere to put a bullet hole.
The problem is that you're using the raycast hit as a local variable, which allows you to use it outside of the scope where it's actually valid.
Delete rayHit from your class and define it in the raycast instead, like
out RaycastHit rayHit
then it should only be scoped for the if statement and you'll get a compiler error anywhere it's not valid.
This brings up a larger question about what do you do if it misses an enemy, or which layers you should be raycasting against. Personally I think you'd want to raycast against everything, then you can try to determine what you hit and what that means later. Only other really good alternative would be to raycast against enemies, then repeat that against objects if that misses, but it's a lot of overhead to keep spinning up the raycasting engine. You'd be better off firing against multiple layers and getting the layer off the collider.
PS too your spread is probably way, way too big. For values of spread, 0.01 is half a degree, 0.1 is five degrees, 1 is 45 degrees.
I found the Problem. Just tell the Gun that the Layer "Ground" is also an Enemy. Now it works. Thanks
Basically you need to Transform Direction e.g camTrans.TransformDirection. You can try this way
public class Raytest : MonoBehaviour
{
public Camera fpsCam;
public float maxDistance = 200f;
public bool update = true;
public GameObject objectToSpawn;
private void Update()
{
if(!update) return;
var camTrans = fpsCam.transform;
if (Physics.Raycast(camTrans.position, camTrans.TransformDirection(Vector3.forward), out var hit, maxDistance))
{
Debug.DrawRay(camTrans.position, camTrans.TransformDirection(Vector3.forward) * hit.distance, Color.red);
Debug.Log("Did Hit");
var clone = Instantiate(objectToSpawn, hit.point, Quaternion.Euler(0, 180, 0));
update = false;
}
else
{
Debug.DrawRay(camTrans.position, camTrans.TransformDirection(Vector3.forward) * 1000, Color.white);
Debug.Log("Did not Hit");
}
}
}
After hitting raycast

Player Object spins continuously when moving joystick

I have created a twin stick movement system for mobile. I have a character moving under the influence of one joystick correctly. The other joystick, the design I want is:
When the shoot JS is moved, look in that direction.
When the shoot JS is released, shoot in the last aimed direction.
What's happening is, the character shoots continuously when the game starts and if I move the ShootJS, the character spins in circles. I'm completely flummoxed as to why this is happening.
Here is my code. Thanks in advance to anybody for any help you provide.
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.AI;
using Ludiq;
using Bolt;
public class PlayerJSControlSc : MonoBehaviour
{
public GameObject player;
public NavMeshAgent nav;
public Text stateText;
public float moveSpeed;
public Animator animator;
public FloatingJoystick moveJS;
public FloatingJoystick shootJS;
public float rotationSpeed = 10;
public int ammo;
public int mag;
public Transform shotSpawn;
public GameObject bullet;
public float reloadTime;
public Text ammoCount;
[HideInInspector]
int currentMag;
// Start is called before the first frame update
void Start()
{
stateText.text = "";
nav = player.GetComponent<NavMeshAgent>();
animator = player.GetComponent<Animator>();
moveJS = GameObject.Find("Floating JS_Move").GetComponent<FloatingJoystick>();
shootJS = GameObject.Find("Floating JS_Shoot").GetComponent<FloatingJoystick>();
}
// Update is called once per frame
void Update()
{
movePlayer();
playerShoot();
ammoCount.text = currentMag+ "/" + ammo;
}
public void movePlayer()
{
//float x = Input.GetAxis("Horizontal");
//float y = Input.GetAxis("Vertical");
float x = moveJS.Horizontal;
float y = moveJS.Vertical;
nav.velocity = new Vector3(x * moveSpeed, 0, y * moveSpeed);
if (nav.velocity.x != 0 || nav.velocity.z != 0)
{ animator.SetBool("isRunning", true); }
else { animator.SetBool("isRunning", false); }
}
public void playerShoot()
{
bool isAiming = false;
float x = shootJS.Horizontal; float z = shootJS.Vertical;
if (x != 0 || z != 0)
{
isAiming = true;
/* Vector3 lookDir = new Vector3(x, 0, z);
Quaternion lookRotation = Quaternion.LookRotation(lookDir, Vector3.up);
float step = rotationSpeed * Time.deltaTime;
player.transform.rotation = Quaternion.RotateTowards(lookRotation, transform.rotation, step);*/
float myAngle = Mathf.Atan2(x, z) * Mathf.Rad2Deg;
float bodyRotation = myAngle + player.transform.eulerAngles.y;
player.transform.Rotate( 0,myAngle,0,Space.World);
}
else { shoot();isAiming = false; }
}
void shoot()
{
if (currentMag > 0)
{
Instantiate(bullet, shotSpawn.position, shotSpawn.rotation);
currentMag--;
}
else if (currentMag=0)
{
StartCoroutine(reload());
}
else
return;
}
IEnumerator reload()
{
ammo = ammo - mag;
currentMag = mag;
yield return new WaitForSeconds(reloadTime);
}
}
well you are calling every frame playerShoot() -> not moving -> shoot().
And in the same way also playerShoot() -> not moving -> player.transform.Rotate( 0,myAngle,0,Space.World);.
I think what you rather should do is
doing the shoot only in the very first frame where both inputs are 0
for the move rather set the rotation instead of increasing it
Something like
private bool lastFrameMoved;
public void playerShoot()
{
float x = shootJS.Horizontal;
float z = shootJS.Vertical;
if (x != 0 || z != 0)
{
var lookDir = new Vector3(x, 0, z);
var lookRotation = Quaternion.LookRotation(lookDir, Vector3.up);
player.transform.rotation = lookRotation;
lastFrameMoved = true;
}
else
{
if(lastFrameMoved)
{
shoot();
}
lastFrameMoved = false;
}
}
I solved the look rotation in Bolt (because it helps me visualize). I'll solve the shoot part soon. I'm using the wonderful Joystick Pack by Fenerax Studios.
https://assetstore.unity.com/publishers/32730

Unity Snake Game, how to make the body follow the head?

So I've been making a small game to do with Snake, and I'm struggling as to how I can make the Snake's Body appear and follow the position of the head whenever the snake's head touches the apple. I've managed to get the Snake's body to spawn but I can't get it to follow the head correctly. Can anyone help me and tell me how I can do this? Thanks!
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Snake_Move : MonoBehaviour
{
// variables
public Vector2 pos;
private Vector2 moveDirection;
private float moveTimer;
private float timerSeconds;
//Function which runs once when the program starts
void Start()
{
timerSeconds = 0.0167f;
moveTimer = timerSeconds;
moveDirection = new Vector2(0.1f, 0);
}
//Function which updates itself based on your refresh rate
public void Update()
{
AutoMove();
ChangeDirection();
transform.position = new Vector2(pos.x, pos.y);
transform.eulerAngles = new Vector3(0, 0, AngleCalculator(moveDirection) - 90);
}
//Moves the snake 60 units each second
private void AutoMove()
{
moveTimer += Time.deltaTime;
if (moveTimer > timerSeconds)
{
pos += moveDirection;
moveTimer -= timerSeconds;
}
}
//Changes direction of the snake based on arrow key pressed
private void ChangeDirection()
{
if (Input.GetKeyDown(KeyCode.UpArrow))
{
if (moveDirection.y != -0.1f)
{
moveDirection.x = 0;
moveDirection.y = 0.1f;
}
}
else if (Input.GetKeyDown(KeyCode.DownArrow))
{
if (moveDirection.y != 0.1f)
{
moveDirection.x = 0;
moveDirection.y = -0.1f;
}
}
else if (Input.GetKeyDown(KeyCode.RightArrow))
{
if (moveDirection.x != -0.1f)
{
moveDirection.y = 0;
moveDirection.x = 0.1f;
}
}
else if (Input.GetKeyDown(KeyCode.LeftArrow))
{
if (moveDirection.x != 0.1f)
{
moveDirection.y = 0;
moveDirection.x = -0.1f;
}
}
}
//Calculates the angle at which the snake is moving; used to calculate rotation of sprite
private float AngleCalculator(Vector2 direction)
{
float angle = Mathf.Atan2(direction.y, direction.x) * Mathf.Rad2Deg;
return angle;
}
private void SnakeBodySprite()
{
GameObject snakeApple = GameObject.Find("SnakeApple");
Apple_RandomSpawn appleScript = snakeApple.GetComponent<Apple_RandomSpawn>();
//something here?????
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Apple_RandomSpawn : MonoBehaviour
{
private Vector2 foodPos;
void Start()
{
SpawnApple();
}
void Update()
{
transform.position = new Vector2(foodPos.x, foodPos.y);
SnakeAte();
}
public void SpawnApple()
{
foodPos = new Vector2(Random.Range(-17, 17), Random.Range(-9, 9));
}
public void SnakeAte()
{
GameObject snakeBody = GameObject.Find("SnakeBody");
GameObject snakeHead = GameObject.Find("SnakeHead");
Snake_Move snakeMove = snakeHead.GetComponent<Snake_Move>();
if (foodPos.x <= snakeMove.pos.x + 1 &&
foodPos.x >= snakeMove.pos.x - 1 &&
foodPos.y <= snakeMove.pos.y + 1 &&
foodPos.y >= snakeMove.pos.y -1)
{
SpawnApple();
Instantiate(snakeBody);
}
}
}
This is kind of a broad question, so it's hard to answer completely. The thought that comes to my mind is using a Queue of move Vectors for the head, and then applying those movements to the body. You would need a reference to the snake body object, and need to know how many movements the head is from the body. It looks like that might be 60 in your case.
I would add the Queue in this section:
Queue<Vector2> moveDirections = new Queue<Vector2>();
SnakeBody snakeBody; // Reference to 1st snake body element
float offset = 60; // ?
private void AutoMove()
{
moveTimer += Time.deltaTime;
// enqueue the most recent moveDirection
moveDirections.Enqueue(moveDirection);
if (moveTimer > timerSeconds)
{
pos += moveDirection;
moveTimer -= timerSeconds;
// Get oldest moveDirection from the head to apply to the body
Vector2 bodyMovement = moveDirections.Dequeue();
snakeBody.transform.Translate(bodyMovement);
}
// If the queue count is greater than how far ahead the head should be from the
// first body element, remove one from queue.
if (moveDirections.Count > offset) {
moveDirections.Dequeue();
}
}
This would only work for the first body element, so you could add a script to each body element keeping track of its child body element. Position the child element with the same logic used above.
NOTE: I haven't tested this, I'm just trying to give a high-level overview of how to solve this problem.

Unity3D - C# 360 Orbital Camera Controller (Gimbal Lock Issue)

I have a stationary cube in my scene that I'm orbiting a camera around. I have my MainCamera nested under a GameObject that I'm calling 'OrbitalCamera'.
I setup the script so that a click (or tap) and drag will rotate the camera around the object in space so it feels like you're rotating the cube (ie: if I click the top of a face on the cube, and pull down, I'm rotating the X value) but you'll actually be rotating the camera.
For the most part, my script works. However, after rotating the Y so much, the camera is upside down and the X gets inverted. Here's my script:
public class OrbitalCamera : MonoBehaviour {
public bool cameraEnabled;
[SerializeField] private float touchSensitivity;
[SerializeField] private float scrollSensitivity;
[SerializeField] private float orbitDampening;
protected Transform xFormCamera;
protected Transform xFormParent;
protected Vector3 localRotation;
protected float cameraDistance;
void Start () {
cameraEnabled = true;
xFormCamera = transform;
xFormParent = transform.parent;
cameraDistance = transform.position.z * -1;
}
void LateUpdate () {
if (cameraEnabled) {
// TODO:: FIX PROBLEM WHERE WHEN CAMERA IS ROTATED TO BE UPSIDEDOWN, CONTROLS GET INVERSED
if (Input.GetMouseButton(0)) {
if (Input.GetAxis("Mouse X") != 0 || Input.GetAxis("Mouse Y") != 0) {
localRotation.x += Input.GetAxis("Mouse X") * touchSensitivity;
localRotation.y -= Input.GetAxis("Mouse Y") * touchSensitivity;
}
}
}
Quaternion qt = Quaternion.Euler(localRotation.y, localRotation.x, 0);
xFormParent.rotation = Quaternion.Lerp(xFormParent.rotation, qt, Time.deltaTime * orbitDampening);
}
}
Is there a good method to achieve this type of 360 camera? I'd like dragging from right to left to always move the camera left and dragging left to right to always move the camera right -- no matter how the camera is oriented.
Perhaps you could clamp the above/below pan at 89 degrees?
I recently helped a friend make a mouse gimbal, and found allowing freedom beyond 89 degrees was problematic and unnecessary. It seems like your application is the same, at least for one of the two planes.
In your LateUpdate() call, you could perhaps add:
localRotation.x += Input.GetAxis("Mouse X") * touchSensitivity;
localRotation.x = Clamp(localRotation.x);
Then, of course, create your clamp function, which should be fairly straight forward:
float Clamp(float val) // prevent values from ~90 - ~270
{
int lowVal = 89;
int highVal = 271;
int midVal = 180;
if (val > lowVal & val < highVal)
{
if (val > midVal) val = highVal;
else val = lowVal;
}
return val;
}
A slightly different application, but I'm sure you can see how I've set this up: I apply rotation in two steps. Step 1 - a simple Rotate() call, Step 2 - clamping some/all of the rotation:
using UnityEngine;
public class MouseGimbal : MonoBehaviour
{
[SerializeField] [Range(0,89)] float maxRotationDegrees = 10.0f; // At 90+ gimbal oddities must be dealt with.
[SerializeField] bool ClampToMaxRotationDegrees = true; // Disable for free rotation.
[SerializeField] float rotationSpeed = 10.0f;
const float fullArc = 360.0f;
const float halfArc = 180.0f;
const float nullArc = 0.0f;
void Update () { Tilt(); }
void Tilt()
{
// Apply the 'pre-clamp' rotation (rotation-Z and rotation-X from X & Y of mouse, respectively).
if (maxRotationDegrees > 0) { SimpleRotation(GetMouseInput()); }
// Clamp rotation to maxRotationDegrees.
if (ClampToMaxRotationDegrees) { ClampRotation(transform.rotation.eulerAngles); }
}
void ClampRotation(Vector3 tempEulers)
{
tempEulers.x = ClampPlane(tempEulers.x);
tempEulers.z = ClampPlane(tempEulers.z);
tempEulers.y = nullArc; // ClampPlane(tempEulers.y); // *See GIST note below...
transform.rotation = Quaternion.Euler(tempEulers);
///Debug.Log(tempEulers);
}
float ClampPlane(float plane)
{
if (OkayLow(plane) || OkayHigh(plane)) DoNothing(); // Plane 'in range'.
else if (BadLow(plane)) plane = Mathf.Clamp(plane, nullArc, maxRotationDegrees);
else if (BadHigh(plane)) plane = Mathf.Clamp(plane, fullArc - maxRotationDegrees, fullArc);
else Debug.LogWarning("WARN: invalid plane condition");
return plane;
}
Vector2 GetMouseInput()
{
Vector2 mouseXY;
mouseXY.x = -Input.GetAxis("Mouse X"); // MouseX -> rotZ.
mouseXY.y = Input.GetAxis("Mouse Y"); // MouseY -> rotX.
return mouseXY;
}
void SimpleRotation(Vector2 mouseXY)
{
Vector3 rotation = Vector3.zero;
rotation.x = mouseXY.y * Time.deltaTime * rotationSpeed;
rotation.z = mouseXY.x * Time.deltaTime * rotationSpeed;
transform.Rotate(rotation, Space.Self);
}
void DoNothing() { }
bool OkayHigh(float test) { return (test >= fullArc - maxRotationDegrees && test <= fullArc); }
bool OkayLow(float test) { return (test >= nullArc && test <= maxRotationDegrees); }
bool BadHigh(float test) { return (test > halfArc && !OkayHigh(test)); }
bool BadLow(float test) { return (test < halfArc && !OkayLow(test)); }
}
When I developed an orbital camera, I created 3 objects:
- x_axis (rotate with vertical mouse moviment)
- y_axis (rotate with horizontal mouse moviment)
- camera (look_at object) (translated Vector3(0,0,-10))

Categories

Resources