I use this code to move and rotate my object, but it moves through the walls. Yes, I have colliders on object and walls, but my object doesn't collide with these walls.
using UnityEngine;
using System.Collections;
public class player_Control : MonoBehaviour {
public float upspeed;
public float downspeed;
public float rotationSpeed;
Transform myTrans;
Vector3 myPos;
Vector3 myRot;
float angle;
void Start() {
myPos = transform.position;
myRot = transform.rotation.eulerAngles;
}
void FixedUpdate() {
angle = transform.eulerAngles.magnitude * Mathf.Deg2Rad;
if (Input.GetKey(KeyCode.RightArrow)) { // ROTATE RIGHT
myRot.z -= rotationSpeed;
}
if (Input.GetKey(KeyCode.LeftArrow)) { // ROTATE LEFT
myRot.z += rotationSpeed;
}
if (Input.GetKey(KeyCode.UpArrow)) { // UP
myPos.y += (Mathf.Cos(-angle) * upspeed) * Time.deltaTime;
myPos.x += (Mathf.Sin(-angle) * upspeed) * Time.deltaTime;
}
if (Input.GetKey(KeyCode.DownArrow)) { // DOWN
myPos.y += (Mathf.Cos(-angle) * -downspeed) * Time.deltaTime;
myPos.x += (Mathf.Sin(-angle) * -downspeed) * Time.deltaTime;
}
transform.position = myPos;
transform.rotation = Quaternion.Euler(myRot);
}
}
Your issue here is that you are bypassing the Unity's physics engine and altering the players position and rotation directly.
Unity's physics checks are built around usage of the Rigidbody component and has several specific functions for changing an objects position and rotation so that it collides correctly with other objects within the scene.
For your usage above I would look at the following two functions for changing position and rotation of your character:
https://docs.unity3d.com/ScriptReference/Rigidbody.MovePosition.html
https://docs.unity3d.com/ScriptReference/Rigidbody.MoveRotation.html
Related
Hello again my friends.
I am trying to make a 3D game in Unity in which I am trying to move my character with simple WASD keys.
However, it is successful only from one direction. From the opposite direction the controls seem reversed. Even when I look around with the mouse. The game is considered to be a First-Person Shooter(FPS).
The Player code is:
[SerializeField]
private NavMeshAgent navMeshAgent;
// Start is called before the first frame update
void Start()
{
controller = GetComponent<CharacterController>();
}
// Update is called once per frame
void Update()
{
Vector3 direction = new Vector3(Input.GetAxis("Horizontal1"), 0, Input.GetAxis("Vertical1"));
Vector3 velocity = direction * speed;
velocity.y -= gravity;
velocity = transform.TransformDirection(velocity);
controller.Move(direction * Time.deltaTime);
transform.position = navMeshAgent.nextPosition;
}
What should I do? I would really appreciate your help.
Try this example to move your character use your own logic ofc and change what have to be changed
private float speed = 2.0f;
public GameObject character;
void Update () {
if (Input.GetKeyDown(d)){
transform.position += Vector3.right * speed * Time.deltaTime;
}
if (Input.GetKeyDown(a)){
transform.position += Vector3.left* speed * Time.deltaTime;
}
if (Input.GetKeyDown(w)){
transform.position += Vector3.forward * speed * Time.deltaTime;
}
if (Input.GetKeyDown(s)){
transform.position += Vector3.back* speed * Time.deltaTime;
}
}
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
So far I have a character controller that enables me to move around, sprint and crouch (no animation) , but I am unable to get the controller to jump. I know 100% the character is getting the input to jump, and the movement vector is around ~40 on the Y axis, so the player should be moving. The problem is, nothing happens. The player can still move around, and fall of ledges, but nothing happens when i press space
This is my code:
using UnityEngine;
public class KeyboardMovement : MonoBehaviour
{
private CharacterController controller;
public float walkSpeed;
public float sprintSpeed;
public float crouchSpeed;
public float jumpHeight;
Vector3 up = Vector3.zero;
Vector3 movement = Vector3.zero;
Vector3 forward = Vector3.zero;
Vector3 sideways = Vector3.zero;
void Start()
{
controller = GetComponent<CharacterController>();
}
void Update()
{
float speed = walkSpeed;
//If crouching, set speed to crouch speed. This ovverides sprinting
if (SingletonSettings.GetKey(SingletonSettings.Keybindings.crouch))
speed = crouchSpeed;
//Else if sprinting, set speed to sprint speed
else if (SingletonSettings.GetKey(SingletonSettings.Keybindings.sprint))
speed = sprintSpeed;
//Create vectors for movement
forward = transform.TransformDirection(Vector3.forward) * Input.GetAxis("Vertical");
sideways = transform.TransformDirection(Vector3.right) * Input.GetAxis("Horizontal");
//up = SingletonSettings.GetKey(SingletonSettings.Keybindings.jump) && controller.isGrounded ? Vector3.up * jumpHeight : Vector3.zero;
movement = (up * 100) + ((forward + sideways) * 10 * Time.deltaTime * speed);
//Combine vectors and Multiply by DeltaTime to ensure smooth movement at different framerates.
//Also multiply by 10*speed to ensure correct speed in different states
if (controller.isGrounded && Input.GetKey(KeyCode.Space))
{
movement.y = jumpHeight*50 * Time.deltaTime;
}
controller.SimpleMove(movement);
}
void OnGUI()
{
GUILayout.Label('\n' + Newtonsoft.Json.JsonConvert.SerializeObject(movement.y, Newtonsoft.Json.Formatting.Indented, new Newtonsoft.Json.JsonSerializerSettings
{
ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore
}));
}
}
CharacterController.SimpleMove from the docs
Moves the character with speed.
Velocity along the y-axis is ignored.
Gravity is automatically applied.
https://docs.unity3d.com/ScriptReference/CharacterController.SimpleMove.html
You should use CharacterController.Move
A more complex move function taking absolute movement deltas.
Attempts to move the controller by motion, the motion will only be constrained by collisions. It will slide along colliders
...
This function does not apply any gravity.
https://docs.unity3d.com/ScriptReference/CharacterController.Move.html
With this method, you'll need to apply gravity yourself
movement.y -= gravity * Time.deltaTime;
controller.Move(movement * Time.deltaTime);
I got a movement relative to the camera. Like Super Mario 64 etc. First i made it with a CharacterController but I want to have the default collision detection so I need to use a collider with a Rigidbody.
My code looks this:
public class PlayerMovementController : PlayerCommonController
{
PlayerMovementData data; // data class
PlayerMovementView view; // animation, etc. ... class
float turnSmoothVelocity;
float speedSmoothVelocity;
private void Start()
{
data = new PlayerMovementData();
view = new PlayerMovementView();
}
private void Update()
{
Vector2 inputDirection = (new Vector2(data.InputHorizontal, data.InputVertical)).normalized; // get the inputs
if (Input.GetButtonDown("Jump"))
{
if (data.PlayerCharacterController.isGrounded) // player is on ground?
data.VelocityY = Mathf.Sqrt(-2 * data.PlayerGravity * data.JumpPower);
}
if (inputDirection != Vector2.zero) // Rotate the player
{
transform.eulerAngles = Vector3.up * Mathf.SmoothDampAngle(
transform.eulerAngles.y,
Mathf.Atan2(inputDirection.x, inputDirection.y) * Mathf.Rad2Deg + data.CameraTransform.eulerAngles.y,
ref turnSmoothVelocity,
GetModifiedSmoothTime(data.TurnSmoothTime));
}
data.CurrentMovementSpeed = Mathf.SmoothDamp( /* Set the movementspeed */
data.CurrentMovementSpeed,
data.MovementSpeed * inputDirection.magnitude,
ref speedSmoothVelocity,
GetModifiedSmoothTime(data.SpeedSmoothTime));
data.VelocityY += data.PlayerGravity * Time.deltaTime; // vertical velocity
Vector3 velocity = transform.forward * data.CurrentMovementSpeed + Vector3.up * data.VelocityY; // set the players velocity
data.PlayerCharacterController.Move(velocity * Time.deltaTime); // Move the player
data.CurrentMovementSpeed = (new Vector2(data.PlayerCharacterController.velocity.x, data.PlayerCharacterController.velocity.z)).magnitude; // Calc movementspeed
if (data.PlayerCharacterController.isGrounded) // Set the vertical vel. to 0 when grounded
data.VelocityY = 0;
}
float GetModifiedSmoothTime(float smoothTime) // Handle the movement while in air
{
if (data.PlayerCharacterController.isGrounded)
return smoothTime;
if (data.AirControlPercentage == 0)
return float.MaxValue;
return smoothTime / data.AirControlPercentage;
}
}
So it seems obvious to replace all the CharacterController variables with a Rigidbody key word. But when it comes to
data.PlayerCharacterController.Move(velocity * Time.deltaTime);
I don't know what to replace there. When I got no CC but a Collider and a Rigidbody i drop through the ground. This may happen because of the code..
Could someone help me out?
Remove CharacterController component from your player and attach a Rigidbody component. Then use
GetComponent<Rigidbody>().velocity = velocity * Time.deltaTime;
I will suggest that you create a reference of you attached rigidbody and use it instead of GetComponent.
This is the script i'm using for testing the movements. The cube is moving forward make a rotation of 180 degrees and stop. The spaceship instead moving forward it's just moving up then in the it rotate and stop.
Why the spaceship is not moving like the cube forward ? I guess it's something with the spaceship physics but not sure if it is the problem and what and how to solve it.
This is a shot video clip i recordered showing the spaceship in hierarchy and it's inspector same for the cube.
Both attached with the same script at below i also show in the video what happening when running the game:
video clip
The problem is that the ship moving up and not forward when doing:
transform.position += transform.forward * Time.deltaTime * moveSpeed;
But the cube does move forward.
using UnityEngine;
using System.Collections;
public class MoveObject : MonoBehaviour {
public float moveSpeed = 1.0f;
public float smooth = 1f;
private float distanceTravelled;
private Vector3 startPositon;
private Vector3 targetAngles;
private bool isRotate = false;
// Use this for initialization
void Start () {
startPositon = new Vector3 (transform.position.x, transform.position.y, transform.position.z);
}
// Update is called once per frame
void Update () {
if (isRotate == false)
transform.position += transform.forward * Time.deltaTime * moveSpeed;
distanceTravelled += Vector3.Distance (transform.transform.position, startPositon);
if (distanceTravelled >= 100 && isRotate == false) {
targetAngles = transform.eulerAngles + 180f * Vector3.up;
StartCoroutine (TurnObject (transform, transform.eulerAngles, targetAngles, smooth));
isRotate = true;
}
}
IEnumerator TurnObject(Transform ship, Vector3 startAngle, Vector3 endAngle, float smooth)
{
float lerpSpeed = 0;
while(lerpSpeed < 1)
{
ship.eulerAngles = Vector3.Lerp(startAngle, endAngle, lerpSpeed);
lerpSpeed += Time.deltaTime * smooth;
yield return null;
}
}
}