How can I avoid code duplication in Unity3d? - c#

How can I shorten this code and avoid copying, what do you advise?
The method is used to move the camera in space using buttons
private void HandleMovementInput() {
if (Input.GetKey(KeyCode.W) || Input.GetKey(KeyCode.UpArrow))
{
new_position += (transform.forward * movement_speed);
}
if (Input.GetKey(KeyCode.S) || Input.GetKey(KeyCode.DownArrow))
{
new_position += (transform.forward * -movement_speed);
}
if (Input.GetKey(KeyCode.D) || Input.GetKey(KeyCode.RightArrow))
{
new_position += (transform.right * movement_speed);
}
if (Input.GetKey(KeyCode.A) || Input.GetKey(KeyCode.LeftArrow))
{
new_position += (transform.right * -movement_speed);
}
if (Input.GetKey(KeyCode.Q))
{
new_rotation *= Quaternion.Euler(Vector3.up * rotation_amount);
}
if (Input.GetKey(KeyCode.E))
{
new_rotation *= Quaternion.Euler(Vector3.up * -rotation_amount);
}
//Shit code for zoom
if (Input.GetKey(KeyCode.R))
{
new_zoom += zoom_amount;
}
if (Input.GetKey(KeyCode.F))
{
new_zoom -= zoom_amount;
}
transform.position = Vector3.Lerp(transform.position, new_position, Time.deltaTime * movement_time);
transform.rotation = Quaternion.Lerp(transform.rotation, new_rotation, Time.deltaTime * movement_time);
camera_transform.localPosition = Vector3.Lerp(camera_transform.localPosition,new_zoom, Time.deltaTime * movement_time);
}
Unfortunately, I'm not so strong in Unity to solve this architectural case.

Try using Input.Getaxis.
https://docs.unity3d.com/ScriptReference/Input.GetAxis.html
I used this code for my player movement script
//playerinput is a Vector3 variable
playerinput = new Vector3(Input.GetAxis("Horizontal"), 0f,
Input.GetAxis("Vertical"));
//transform.TransformDirection is here to move the player depending in their rotation
//playerinput.normalized is there for stopping strafing(for example, holding w and s together makes the player faster)
//I don't think you should change Mathf.Clamp01(playerinput.magnitude). This is very important for the movement to look good.
Vector3 movevector = transform.TransformDirection(playerinput.normalized * Mathf.Clamp01(playerinput.magnitude)) * speed;
//rb is the rigidbody by the way. Add rigidbody component to your camera
rb.velocity = new Vector3(movevector.x, rb.velocity.y, movevector.z);
This will do the trick, you can remove some lines of code to fit your game. Hope this helped!

Related

Gravity increases drastically when walking off edge when comparted to jumping

void UpdateMovement()
{
Vector2 targetDir = new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical"));
targetDir.Normalize();
currentDir = Vector2.SmoothDamp(currentDir, targetDir, ref currentDirVelocity, moveSmoothTime);
if (controller.isGrounded)
{
velocityY = -gravity;
}
// jump
if (controller.isGrounded && Input.GetKeyDown(KeyCode.Space))
{
velocityY = jumpForce;
}
// sprint
if (Input.GetKey(KeyCode.LeftShift))
{
velocity = (transform.forward * currentDir.y + transform.right * currentDir.x) * sprintSpeed + Vector3.up * velocityY;
}
else
{
velocity = (transform.forward * currentDir.y + transform.right * currentDir.x) * walkSpeed + Vector3.up * velocityY;
}
velocityY -= gravity * Time.deltaTime;
Debug.Log(velocityY);
controller.Move(velocity * Time.deltaTime);
}
This is the code that I am using to move and jump in my game. Those functions work fine, the problem is in the gravity when walking off a surface. When jumping gravity works as intended but when falling without jumping (walking off the edge) gravity is still set to it's default value (15) so the characters falls incredibly fast.
I understand that this is caused by having no function to change this value when falling from an edge but I have found no way of making this happen without breaking all of the vertical movement.
You can reset the gravity as Brackeys did in his FPS Controller Tutorial:
if (isGrounded) {
velocityY = -2f;
}

Top down game in Unity. Player can't stop moving

i've following issue. I'm trying to make game with top down view (something like first GTA game). The problem is when i press the key my player is moving, but can't stop. Here you can see my script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovemenet : MonoBehaviour
{
private Rigidbody2D m_Rigidbody;
private Transform playerTransform;
public float m_Speed = 100.0f;
// Start is called before the first frame update
void Start()
{
m_Rigidbody = GetComponent<Rigidbody2D>();
playerTransform = GameObject.Find("Player").transform;
}
// Update is called once per frame
void FixedUpdate()
{
Vector3 playerPos = playerTransform.eulerAngles;
if (Input.GetKey(KeyCode.UpArrow))
{
m_Rigidbody.velocity= transform.up * Time.deltaTime * m_Speed;
}
if (Input.GetKey(KeyCode.DownArrow))
{
m_Rigidbody.velocity = transform.up * Time.deltaTime * (-m_Speed);
}
if (Input.GetKey(KeyCode.RightArrow))
{
transform.Rotate(0, 0, -1 * m_Speed * Time.deltaTime);
}
if (Input.GetKey(KeyCode.LeftArrow))
{
transform.Rotate(0, 0, 1 * m_Speed * Time.deltaTime);
}
}
}
'''
Can you please tell me how to fix it? Thanks for your answers.
Note that in general a velocity already is a value in absolute units per second and you don't want to multiply by Time.deltaTime in that case.
Also in general whenever dealing with Physics I wouldn't use transform at all but rather do everything via the Rigidbody.
And then simply when you don't press a key do
if (Input.GetKey(KeyCode.UpArrow))
{
m_Rigidbody.velocity = Quaternion.Euler(0, 0, m_Rigidbody.rotation) * Vector3.up * m_Speed;
}
else if (Input.GetKey(KeyCode.DownArrow))
{
m_Rigidbody.velocity = Quaternion.Euler(0, 0, m_Rigidbody.rotation) * Vector3.down * m_Speed;
}
else
{
m_Rigidbody.velocity = Vector2.zero;
}
For the rotation I would also rather go
m_Rigidbody.rotation += m_Speed * Time.deltaTime;
and
m_Rigidbody.rotation -= m_Speed * Time.deltaTime;

Camera resets keyboard rotation before applying mouse rotation

I'm having an issue with the free roam camera I'm trying to implement. The camera can be rotated via keyboard (only on the Y axis) and via mouse (on the X and Y axis) while holding the middle mouse button. With my current implementation, if I rotate the camera using the keyboard and the rotate it using the mouse, it remove any rotation done by the keyboard as soon as I hit the middle mouse button. Of course I would like to not do that... Code is below. Can someone give tell me what I'm doing wrong?
private void RotateCameraKeyboard()
{
if (Input.GetKey(KeyCode.Q))
{
transform.RotateAround(transform.position, Vector3.up, -rotationSpeed * Time.deltaTime * 30);
}
if (Input.GetKey(KeyCode.E))
{
transform.RotateAround(transform.position, Vector3.up, rotationSpeed * Time.deltaTime * 30);
}
}
private void RotateCameraMouse()
{
if (Input.GetMouseButton(2))
{
pitch -= rotationSpeed * Input.GetAxis("Mouse Y");
yaw += rotationSpeed * Input.GetAxis("Mouse X");
pitch = Mathf.Clamp(pitch, -90f, 90f);
while (yaw < 0f)
{
yaw += 360f;
}
while (yaw >= 360f)
{
yaw -= 360f;
}
transform.eulerAngles = new Vector3(pitch, yaw, 0f);
}
}
Instead of using RotateAround (which in your case of using the transform.position as pivot is redundant anyway .. you could as well just use Rotate) additionally also add the according amount to your pitch and yawn.
I would simply generalize and use the same method for both inputs like e.g.
private void RotateCameraKeyboard()
{
if (Input.GetKey(KeyCode.Q))
{
Rotate(-rotationSpeed * Time.deltaTime * 30, 0);
}
if (Input.GetKey(KeyCode.E))
{
Rotate(rotationSpeed * Time.deltaTime * 30, 0);
}
}
private void RotateCameraMouse()
{
if (Input.GetMouseButton(2))
{
var pitchChange = rotationSpeed * Input.GetAxis("Mouse Y");
var yawChange = rotationSpeed * Input.GetAxis("Mouse X");
Rotate(yawChange, pitchChange);
}
}
private void Rotate(float yawChange, float pitchChange)
{
pitch = Mathf.Clamp(pitch + pitchChange, -90f, 90f);
yaw += yawChange;
while (yaw < 0f)
{
yaw += 360f;
}
while (yaw >= 360f)
{
yaw -= 360f;
}
transform.eulerAngles = new Vector3(pitch, yaw, 0f);
}

How do I make the camera stay within a sphere?

I can make the camera move the way I want, but I need it to be confined to within the 3D hollow sphere that I created. Currently the player can fly the camera out of the game area.
I've tried parenting the camera to a spherical game object, but the camera still leaves the game area but the sphere stays inside.
This was my attempt at using the BoundingSphere method to keep the camera inside the sphere.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SphericalBoundary : MonoBehaviour
{
public Vector3 pos;
public float r;
void Start()
{
BoundingSphere();
}
private void FixedUpdate()
{
BoundingSphere();
}
public void BoundingSphere()
{
pos = new Vector3(0, 0, 0);
r = (100);
}
}
============================================================================
============================================================================
This is the script that makes the camera fly around. Works perfectly.
using UnityEngine;
using System.Collections;
public class CameraFlight : MonoBehaviour
{
/*
EXTENDED FLYCAM
Desi Quintans (CowfaceGames.com), 17 August 2012.
Based on FlyThrough.js by Slin (http://wiki.unity3d.com/index.php/FlyThrough), 17 May 2011.
LICENSE
Free as in speech, and free as in beer.
FEATURES
WASD/Arrows: Movement
Q: Climb
E: Drop
Shift: Move faster
Control: Move slower
End: Toggle cursor locking to screen (you can also press Ctrl+P to toggle play mode on and off).
*/
public float cameraSensitivity = 90;
public float climbSpeed = 4;
public float normalMoveSpeed = 10;
public float slowMoveFactor = 0.25f;
public float fastMoveFactor = 3;
private float rotationX = 0.0f;
private float rotationY = 0.0f;
void Start()
{
// Screen.lockCursor = true;
}
void Update()
{
rotationX += Input.GetAxis("Mouse X") * cameraSensitivity * Time.deltaTime;
rotationY += Input.GetAxis("Mouse Y") * cameraSensitivity * Time.deltaTime;
rotationY = Mathf.Clamp(rotationY, -90, 90);
transform.localRotation = Quaternion.AngleAxis(rotationX, Vector3.up);
transform.localRotation *= Quaternion.AngleAxis(rotationY, Vector3.left);
if (Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift))
{
transform.position += transform.forward * (normalMoveSpeed * fastMoveFactor) * Input.GetAxis("Vertical") * Time.deltaTime;
transform.position += transform.right * (normalMoveSpeed * fastMoveFactor) * Input.GetAxis("Horizontal") * Time.deltaTime;
}
else if (Input.GetKey(KeyCode.LeftControl) || Input.GetKey(KeyCode.RightControl))
{
transform.position += transform.forward * (normalMoveSpeed * slowMoveFactor) * Input.GetAxis("Vertical") * Time.deltaTime;
transform.position += transform.right * (normalMoveSpeed * slowMoveFactor) * Input.GetAxis("Horizontal") * Time.deltaTime;
}
else
{
transform.position += transform.forward * normalMoveSpeed * Input.GetAxis("Vertical") * Time.deltaTime;
transform.position += transform.right * normalMoveSpeed * Input.GetAxis("Horizontal") * Time.deltaTime;
}
if (Input.GetKey(KeyCode.Q)) { transform.position += transform.up * climbSpeed * Time.deltaTime; }
if (Input.GetKey(KeyCode.E)) { transform.position -= transform.up * climbSpeed * Time.deltaTime; }
//if (Input.GetKeyDown(KeyCode.End))
//{
// Screen.lockCursor = (Screen.lockCursor == false) ? true :][1]
false;
//}
}
}
No errors are showing up. During play the player can fly the camera out of the sphere but I want them confined to the sphere.
I think you must look your camera position on every frame and also check if it's going out of bound of the sphere here is some code which might help you(it is not tested)
public class TestScriptForStackOverflow : MonoBehaviour {
public Transform CameraTrans, SphereTrans;
private float _sphereRadius;
void Start() {
//if we are talking about sphere its localscale.x,y,z values are always equal
_sphereRadius = SphereTrans.localScale.x / 2;
}
void Update() {
if (IsOutsideTheSphere(_sphereRadius, CameraTrans.position, SphereTrans.position)) {
//lets find direction of camera from sphere center
Vector3 direction = (CameraTrans.position - SphereTrans.position).normalized;
//this is bound point for specific direction which is point is on the end of the radius
Vector3 boundPos = SphereTrans.position + direction * _sphereRadius;
//finally assign bound position to camera to stop it to pierce the sphere bounds
CameraTrans.position = boundPos;
}
}
private bool IsOutsideTheSphere(float sphereRadius, Vector3 cameraPosition, Vector3 sphereCenterPosition) {
//distance betweeen cameraPosition and sphereCenterPosition
float distanceBetween = (cameraPosition - sphereCenterPosition).magnitude;
//returns true if distance between sphere center and camera position is longer then sphere radius
return distanceBetween > sphereRadius;
}
If there is something you don't understand ask me in comments

Make player move forward,right,left and backwards based on camera angle

So far I have a player who moved forward left right and backwards, however how I have it set up it's forward as in forward on the grid, not forward where my player is looking. I have the camera set as FPS, with it following the player around. Now I want to have the player be able to look with my MouseLook script (works already) but based on that I want forward to be wherever the player is looking, not the primitive version I have. I'll post code below to let you know what I am talking about, ANY help is appreciated.
Player Script (movement)
void Update () {
if(Input.GetKey (moveU))
{
SetTransformZ((transform.position.z) + playerSpeed);
}
if(Input.GetKey (moveD))
{
SetTransformZ((transform.position.z) - playerSpeed);
}
if(Input.GetKey (moveL))
{
SetTransformX((transform.position.x) - playerSpeed);
}
if(Input.GetKey (moveR))
{
SetTransformX((transform.position.x) + playerSpeed);
}
else
{
rigidbody.angularVelocity = Vector3.zero;
}
}
void SetTransformX(float n)
{
transform.position = new Vector3(n, transform.position.y, transform.position.z);
}
void SetTransformZ(float n)
{
transform.position = new Vector3(transform.position.x, transform.position.y, n);
}
MouseLook script (attached to Main Camera in Unity, this works witht he player so it goes whereever my mouse is looking, but the movement is off since my code to move is very primitive)
[AddComponentMenu("Camera-Control/Mouse Look")]
public class MouseLook : MonoBehaviour {
public enum RotationAxes {
MouseXAndY = 0,
MouseX = 1,
MouseY = 2 }
public RotationAxes axes = RotationAxes.MouseXAndY;
public float sensitivityX = 15F;
public float sensitivityY = 15F;
public float minimumX = -360F;
public float maximumX = 360F;
public float minimumY = -60F;
public float maximumY = 60F;
float rotationY = 0F;
void Update ()
{
if (axes == RotationAxes.MouseXAndY)
{
float rotationX = transform.localEulerAngles.y + Input.GetAxis("Mouse X") * sensitivityX;
rotationY += Input.GetAxis("Mouse Y") * sensitivityY;
rotationY = Mathf.Clamp (rotationY, minimumY, maximumY);
transform.localEulerAngles = new Vector3(-rotationY, rotationX, 0);
}
else if (axes == RotationAxes.MouseX)
{
transform.Rotate(0, Input.GetAxis("Mouse X") * sensitivityX, 0);
}
else
{
rotationY += Input.GetAxis("Mouse Y") * sensitivityY;
rotationY = Mathf.Clamp (rotationY, minimumY, maximumY);
transform.localEulerAngles = new Vector3(-rotationY, transform.localEulerAngles.y, 0);
}
}
void Start ()
{
//if(!networkView.isMine)
//enabled = false;
// Make the rigid body not change rotation
//if (rigidbody)
//rigidbody.freezeRotation = true;
}
Okay, so you want your player to move forward, left, right, back relative to where they are looking, as I understand it.
First, make sure that transform.forward is the right direction for your player. in the editor you can select your player gameObject and see if the blue arrow faces the same direction as your player. If not, check out this thread on the unity answers forum to see how to change it.
Here are some functions to put into your player controller script to move relative to player rotation rather than position.
(Note: check out Time.deltaTime)
private void moveForward(float speed) {
transform.localPosition += transform.forward * speed * Time.deltaTime;
}
private void moveBack(float speed) {
transform.localPosition -= transform.forward * speed * Time.deltaTime;
}
private void moveRight(float speed) {
transform.localPosition += transform.right * speed * Time.deltaTime;
}
private void moveLeft(float speed) {
transform.localPosition -= transform.right * speed * Time.deltaTime;
}
Note: transform.position vs transform.localPosition

Categories

Resources