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;
Related
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
I'm fairly new to unity and C# and I'm trying to understand how to change the gravity scale of my character when I press the space bar. When I debug it, it says that Rigidbody2D.gravityScale cannot be used as a method. Can someone explain why it brings this error and how to fix it?
public class PlayerMovement : MonoBehaviour {
public float moveSpeed;
private Rigidbody2D rb2d;
public float addGrav;
// Use this for initialization
void Start () {
rb2d = GetComponent<Rigidbody2D> ();
}
// Update is called once per frame
void Update () {
//Understanding::: If key pressed down,
//Transform - method that manipulates position of object
//Translate moves transform in direction/distance of translation.
//transform.Translate(translation);
if (Input.GetKey (KeyCode.UpArrow))
{
transform.Translate (Vector2.up * moveSpeed * Time.deltaTime);
}
if (Input.GetKey (KeyCode.DownArrow))
{
transform.Translate (Vector2.down * moveSpeed * Time.deltaTime);
}
if (Input.GetKey (KeyCode.LeftArrow))
{
transform.Translate (Vector2.left * moveSpeed * Time.deltaTime);
}
if (Input.GetKey (KeyCode.RightArrow))
{
transform.Translate (Vector2.right * moveSpeed * Time.deltaTime);
}
if(Input.GetKey (KeyCode.Space))
{
rb2d.gravityScale (addGrav);
}
}
}
rb2d.gravityScale is not a method, it's a field that you can assign value to.
use this
rb2d.gravityScale = addGrav; //to asign
//other example
rb2d.gravityScale += addGrav; //to add
rb2d.gravityScale -= addGrav; //to substract
It's because the compiler were reading it as a method since you used parentheses instead of equal sign. it should be like so.
rb2d.gravityScale = addGrav;
The base is a red cube.
The spaceship is moving already when the game start.
When I click/press the L button the spaceship rotates to face the base and starts moving to it but then when it's getting close to the base it's behaving unexpectedly and the spaceship starts rolling around the base nonstop.
What I want is to make the landing automatic like this youtube video of blender.
I don't want the graphics but the way it's landing.
Blender landing spaceship
And this is a short video clip showing my spaceship when it's start landing:
Landing test
This is the script i'm using for controlling the spaceship and the landing part should be automatic.
The script is attached to the spaceship.
using UnityEngine;
using System.Collections;
public class ControlShip : MonoBehaviour {
public int rotationSpeed = 75;
public int movementspeed = 10;
public int thrust = 10;
public float RotationSpeed = 5;
private bool isPKeyDown = false;
private float acceleration = .0f;
private Vector3 previousPosition = Vector3.zero;
private Rigidbody _rigidbody;
private bool landing = false;
private Vector3 originPosition;
private Vector3 lastPosition;
private const float minDistance = 0.2f;
private Transform baseTarget;
// Use this for initialization
void Start () {
baseTarget = GameObject.Find("Base").transform;
originPosition = transform.position;
_rigidbody = GetComponent<Rigidbody>();
Debug.Log("Acc Speed: " + thrust);
}
// Update is called once per frame
void Update()
{
if (landing == false)
{
var v3 = new Vector3(Input.GetAxis("Vertical"), Input.GetAxis("Horizontal"), 0.0f);
transform.Rotate(v3 * rotationSpeed * Time.deltaTime);
transform.position += transform.forward * Time.deltaTime * movementspeed;
if (Input.GetKey(KeyCode.Z))
transform.Rotate(Vector3.forward * rotationSpeed * Time.deltaTime);
if (Input.GetKey(KeyCode.R))
transform.Rotate(Vector3.right * rotationSpeed * Time.deltaTime);
if (Input.GetKey(KeyCode.P))
{
isPKeyDown = Input.GetKey(KeyCode.P);
float distance = Vector3.Distance(previousPosition, transform.position);
acceleration = distance / Mathf.Pow(Time.deltaTime, 2);
previousPosition = transform.position;
_rigidbody.AddRelativeForce(0f, 0f, thrust, ForceMode.Acceleration);
}
}
else
{
transform.position += transform.forward * Time.deltaTime * movementspeed;
var targetRotation = Quaternion.LookRotation(baseTarget.position - transform.position);
var str = Mathf.Min(.5f * Time.deltaTime, 1);
transform.rotation = Quaternion.Lerp(transform.rotation, targetRotation, str);
}
if (landed == true)
TakeOff();
if (Input.GetKey(KeyCode.L))
{
landing = true;
lastPosition = transform.position;
}
}
void OnTriggerEnter(Collider other)
{
if (landing == true && other.gameObject.name == "Base")
{
StartCoroutine(Landed());
}
}
bool landed = false;
IEnumerator Landed()
{
yield return new WaitForSeconds(5);
Debug.Log("Landed");
landed = true;
}
private void TakeOff()
{
if (transform.position != originPosition)
{
_rigidbody.AddForce(transform.up * 10);
}
if ((transform.position - originPosition).sqrMagnitude <= (1f * 1f))
{
landed = false;
_rigidbody.useGravity = false;
}
}
void OnGUI()
{
if (isPKeyDown)
{
GUI.Label(new Rect(100, 100, 200, 200), "Acc Speed: " + acceleration);
}
}
}
This is the part of the landing, should be the part of the landing:
transform.position += transform.forward * Time.deltaTime * movementspeed;
var targetRotation = Quaternion.LookRotation(baseTarget.position - transform.position);
var str = Mathf.Min(.5f * Time.deltaTime, 1);
transform.rotation = Quaternion.Lerp(transform.rotation, targetRotation, str);
The spaceship have two components: Rigidbody, Use Gravity set to true. And a Box Collider.
The Base have a box collider component.
You appear to have a box collider on your vehicle and it looks as though it is colliding with the terrain when your code tries to bring it in for a landing. Try switching the collider to be a trigger(tick option on collider component).
Then try it again, as this will not cause physical collisions. If it works or fails for a totally different reason you know this is the cause or a contributing factor.
EDIT: It is worth also noting that when trying to achieve this kind of effect it can be much easier to trigger an animation than try to achieve it in physics based code. Unity offers some great animation controllers and you can call an animation when you need to land since you are taking control away from the player anyway.
While doing this you could turn off the collider so you don't get any strange collision then turn it on when the ship needs to take off, provided you need that of course.
Hope it helps.
I'm having an issue where my gameObject barely jumps at all. I think it has something to do with moveDirection because the jumping works when I comment out p.velocity = moveDirection.
Any suggestions on how to fix this?
using UnityEngine;
using System.Collections;
public class Controller : MonoBehaviour
{
public float jumpHeight = 8f;
public Rigidbody p;
public float speed = 1;
public float runSpeed = 3;
public Vector3 moveDirection = Vector3.zero;
// Use this for initialization
void Start ()
{
p = GetComponent<Rigidbody>();
p.velocity = Vector3.zero;
}
// Update is called once per frame
void Update ()
{
if (Input.GetKeyDown (KeyCode.Space))
{
p.AddForce(new Vector3(0, jumpHeight, 0), ForceMode.Impulse);
}
Move ();
}
void Move ()
{
if(Input.GetKey(KeyCode.D))
{
transform.Rotate(Vector3.up, Mathf.Clamp(180f * Time.deltaTime, 0f, 360f));
}
if(Input.GetKey(KeyCode.A))
{
transform.Rotate(Vector3.up, -Mathf.Clamp(180f * Time.deltaTime, 0f, 360f));
}
moveDirection = new Vector3(Input.GetAxis("Horizontal"),0,Input.GetAxis("Vertical"));
moveDirection = transform.TransformDirection(moveDirection);
if(Input.GetKey(KeyCode.LeftShift))
{
moveDirection *= runSpeed;
}
else
{
moveDirection *= speed;
}
p.velocity = moveDirection;
}
}
Try using a much higher value for your jumpheight variable. I usually go with something in the hundreds.
Because right after doing the AddForce(...) literally within the same frame you override the velocity with moveDirection. You should be adding to the current velocity, instead of overriding it entirely as such:
Vector3 velocity = p.velocity;
p.velocity = velocity + moveDirection;
This is exactly why Unity warns against messing with velocity directly, youd be better off just doing another AddForce(...) for your movement:
p.AddForce(moveDirection * Time.deltaTime);
EDIT:
i don't like digressing too far from the OP's question, but your new problems are probably because you are doing too much with moveDirection half of what i don't even understand why but it should for the most part look like this:
moveDirection = new Vector3(Input.GetAxis("Horizontal"),0,Input.GetAxis("Vertical")).normalized;
float _speed = Input.GetKey(KeyCode.LeftShift) ? runspeed : speed;
p.AddForce(moveDirection * _speed * Time.deltaTime);
Okay I figured out how to fix it. Instead of those MoveDirection variables I changed it to
if(Input.GetKey(KeyCode.W)) {
transform.position += transform.forward * Time.deltaTime * speed;
}
if(Input.GetKey(KeyCode.S)) {
transform.position -= transform.forward * Time.deltaTime * speed;
}
and now it works just fine.
In my game I have a camera and I want to have an FPS like rotation attached to this camera.
So if I move my cursor to the left, I want my cam to rotate to the left. If I move my cursor up, then the cam should look up, etc.
I currently have it partially working. I can look left and right, up, and down. The problem occurs when I look down and then move my cursor left and right. It then gives me a "Roll" effect.
See this video to see exactly what I mean:
http://www.screencast.com/t/Phedh8H0K13
Obviously when I look down I still want to have a "Yaw" effect instead of a "Roll" effect. Anyone any idea how to do that? This is what I have so far:
// Update is called once per frame
public override void update ()
{
this.camera.transform.rotation *=
Quaternion.AngleAxis( Time.deltaTime * sensitivityRoll * Input.GetAxis("Vertical"), Vector3.forward );
this.camera.transform.rotation *=
Quaternion.AngleAxis( Time.deltaTime * sensitivityYaw * Input.GetAxis("Mouse X"), Vector3.up );
this.camera.transform.rotation *=
Quaternion.AngleAxis( Time.deltaTime * sensitivityPitch * Input.GetAxis("Mouse Y"), Vector3.left );
}
I just found my answer in this topic:
http://forum.unity3d.com/threads/109250-Looking-with-the-Mouse?highlight=person+camera
The code from that topic:
C# Mono code:
using UnityEngine;
using System.Collections;
/// MouseLook rotates the transform based on the mouse delta.
/// Minimum and Maximum values can be used to constrain the possible rotation
/// To make an FPS style character:
/// - Create a capsule.
/// - Add the MouseLook script to the capsule.
/// -> Set the mouse look to use LookX. (You want to only turn character but not tilt it)
/// - Add FPSInputController script to the capsule
/// -> A CharacterMotor and a CharacterController component will be automatically added.
/// - Create a camera. Make the camera a child of the capsule. Reset it's transform.
/// - Add a MouseLook script to the camera.
/// -> Set the mouse look to use LookY. (You want the camera to tilt up and down like a head. The character already turns.)
[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;
}
}
Simple Script, Not Sure it will work with you, might as well give it a try
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Security.Cryptography;
using System.Threading;
using UnityEngine;
public class mouse_lookat : MonoBehaviour
{
public float mouseSensitivity = 100f;
public Transform playerBody;
float xRotation = 0f;
// Start is called before the first frame update
void Start()
{
Cursor.lockState = CursorLockMode.Locked;
}
// Update is called once per frame
void Update()
{
float mouseX = Input.GetAxis("Mouse X") * mouseSensitivity * Time.deltaTime;
float mouseY = Input.GetAxis("Mouse Y") * mouseSensitivity * Time.deltaTime;
xRotation -= mouseY;
xRotation = Mathf.Clamp(xRotation, -90f, 90f);
transform.localRotation = Quaternion.Euler(xRotation, 0f, 0f);
playerBody.Rotate(Vector3.up * mouseX);
}
}
using UnityEngine;
public class CameraRotator : MonoBehaviour
{
[SerializeField] private Transform _head;
[SerializeField] private float _sensitivity;
[SerializeField] private bool _invertVertical;
private void Update()
{
var deltaMouse = new Vector2(Input.GetAxisRaw("Mouse X"), Input.GetAxisRaw("Mouse Y");
Vector2 deltaRotation = deltaMouse * _sensitivity;
deltaRotation.y *= _invertVertical ? 1.0f : -1.0f;
float pitchAngle = _head.localEulerAngles.x;
// turns 270 deg into -90, etc
if (pitchAngle > 180)
pitchAngle -= 360;
pitchAngle = Mathf.Clamp(pitchAngle + deltaRotation.y, -90.0f, 90.0f);
transform.Rotate(Vector3.up, deltaRotation.x);
_head.localRotation = Quaternion.Euler(pitchAngle, 0.0f, 0.0f);
}
}
i created 2 scripts for my FPS project that work flawlessly for my movement (currently havnt added jump mechanics) and it seems like youve overcomplicated alot of things that can be quite simple and straight forward.
im also new to coding so please correct me if im wrong heres my code
// this is in the player script which i put on an empty parent object of the camera and player sprite
public class player : MonoBehaviour
{
[Header("player Movement")]
[SerializeField] float moveSpeed = 5f;
[SerializeField] public float mouseSensitivity = 5f;
Rigidbody rigidBody;
// Use this for initialization
void Start()
{
}
void Update()
{
Move();
}
private void Move()
{
transform.Translate(Vector3.forward * Input.GetAxis("Vertical") * moveSpeed * Time.deltaTime);
transform.Translate(Vector3.right * Input.GetAxis("Horizontal") * moveSpeed * Time.deltaTime);
transform.Rotate(Vector3.up * Input.GetAxis("Mouse X") * mouseSensitivity);
}
//this is the camera movement script which i put on the camera(will also use this script to add a function to change from 1st person to 3rd person for certain abilities)
{
player player;
// Use this for initialization
void Start()
{
player = FindObjectOfType<player>();
}
// Update is called once per frame
void Update()
{
MoveView();
}
private void MoveView()
{
transform.Rotate(Vector3.left * Input.GetAxis("Mouse Y") * player.mouseSensitivity);
}
}