I have implemented a bow and arrow script in unity5. But the arrow doesn't fly off. Can someone suggest why this happens. I'm a beginner.
This is the Bow Script.
using UnityEngine;
using System.Collections;
public class Bow : MonoBehaviour {
private GameObject arrow = null;
private Vector3 fwd = Vector3.zero;
public GameObject arrowPrefab = null;
public int initialSpeed = 30;
public GameObject launchPosition = null;
public float waitTime = 0.1f;
public LayerMask layerMask;
// Use this for initialization
void Start ()
{
}
void FixedUpdate()
{
fwd = transform.TransformDirection(Vector3.forward);
if (!Physics.Raycast(transform.position, fwd, 1, layerMask))
{
if (Input.GetMouseButtonDown(0))
{
Fire();
}
}
}
private void Fire()
{
//yield return new WaitForSeconds(waitTime);
new WaitForSeconds(waitTime);
arrow = (GameObject)Instantiate(arrowPrefab, launchPosition.transform.position, launchPosition.transform.rotation);
}
}
This is the Arrow Script
using UnityEngine;
using System.Collections;
public class Arrow : MonoBehaviour {
private Vector3 velocity = Vector3.zero;
private Vector3 newPos;
private Vector3 oldPos;
private bool hasHit = false;
private Vector3 direction;
private RaycastHit hit;
private GameObject follow;
private Vector3 dir;
private float dist;
public LayerMask layerMask;
public float speed;
public Transform arrowRotation;
public float forceToApply;
public float arrowGravity;
void Start()
{
newPos = transform.position;
oldPos = newPos;
velocity = speed * transform.forward;
}
void update()
{
if (hasHit)
{
transform.position = follow.transform.position;
transform.rotation = follow.transform.rotation;
return;
}
newPos += (velocity + direction) * Time.deltaTime;
dir = newPos - oldPos;
dist = dir.magnitude;
dir /= dist;
if(dist > 0)
{
if (Physics.Raycast(oldPos,dir,out hit,dist,layerMask))
{
newPos = hit.point;
if (hit.collider)
{
if (hit.rigidbody)
{
GameObject hitpoint = (GameObject)Instantiate(new GameObject(), hit.point, transform.root.rotation);
hitpoint.transform.parent = hit.transform;
follow = hitpoint;
GetComponent<Collider>().isTrigger = true;
hit.rigidbody.AddForceAtPosition(forceToApply * dir, hit.point);
hasHit = true;
}
else
{
enabled = false;
}
}
}
}
oldPos = transform.position;
transform.position = newPos;
velocity.y -= arrowGravity * Time.deltaTime;
arrowRotation.transform.rotation = Quaternion.LookRotation(dir);
}
}
You declare, but do not define 'direction' in your Arrow script. I suspect including it in the newPos calculation means nothing gets added.
Related
I have something strange happening in my game.I use 3d models and a fixed camera to make a 2D platformer. I have a charactercontroller with the following script for movement and jumping:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
private CharacterController controller;
private Vector3 playerVelocity;
private bool groundedPlayer;
[SerializeField] private Animator _animator;
[SerializeField] private float playerSpeed = 2.0f;
[SerializeField] private float jumpHeight = 4.0f;
[SerializeField] private float gravityValue = -1f;
[SerializeField] private AudioSource _audioSource;
[SerializeField] private AudioClip _stepStone;
private void Start()
{
controller = GetComponent<CharacterController>();
_animator = GetComponent<Animator>();
_audioSource = GetComponent<AudioSource>();
}
void Update()
{
MovePlayer();
}
private void MovePlayer()
{
float x = Input.GetAxis("Horizontal");
groundedPlayer = controller.isGrounded;
if (groundedPlayer && playerVelocity.y < 0)
{
playerVelocity.y = 0f;
_animator.SetBool("Jumping", false);
}
Vector3 move = new Vector3(x, 0,0);
controller.Move(move * Time.deltaTime * playerSpeed);
if (move != Vector3.zero)
{
gameObject.transform.forward = move;
}
// Changes the height position of the player..
if (Input.GetButtonDown("Jump") && groundedPlayer)
{
_animator.SetBool("Jumping", true);
playerVelocity.y += Mathf.Sqrt(jumpHeight * -3.0f * gravityValue);
}
playerVelocity.y += gravityValue * Time.deltaTime;
controller.Move(playerVelocity * Time.deltaTime);
if (groundedPlayer)
{
_animator.SetInteger("Speed", Convert.ToInt32(x));
}
}
public void playStoneStep()
{
_audioSource.PlayOneShot(_stepStone);
}
}
My character bounces if it jumps on platforms but not when falling on them. I tried a non bouncy material. how can I fix this?
Here is a video showing it : https://youtu.be/ZhV8nHklsH8
I would do this by adding something that checks if you land on the floor. I did below split your functionality into different, more manageable parts. I've added a layer mask which you will need to configure with the layer of the ground.
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement: MonoBehaviour
{
private CharacterController controller;
private Vector3 playerVelocity;
private bool groundedPlayer;
[SerializeField] private Animator _animator;
[SerializeField] private float playerSpeed = 2.0f;
[SerializeField] private float jumpHeight = 4.0f;
[SerializeField] private float gravityValue = -1f;
[SerializeField] privateLayerMask groundMask;
[SerializeField] private AudioSource _audioSource;
[SerializeField] private AudioClip _stepStone;
private void Start()
{
controller = GetComponent<CharacterController>();
_animator = GetComponent<Animator>();
_audioSource = GetComponent<AudioSource>();
}
void Update()
{
HandleMovement();
HandleJump();
HandleGravity();
}
private void HandleMovement()
{
controller.Move(new Vector3(Input.GetAxis("Horizontal"), 0,0) * Time.deltaTime * playerSpeed);
if (groundedPlayer)
{
_animator.SetInteger("Speed", Convert.ToInt32(x));
}
}
private void HandleJump()
{
if (Input.GetButtonDown("Jump") && groundedPlayer)
{
_animator.SetBool("Jumping", true);
playerVelocity.y += Mathf.Sqrt(jumpHeight * -3.0f * gravityValue);
}
}
private void HandleGravity()
{
playerVelocity.y += gravityValue * Time.deltaTime;
controller.Move(playerVelocity * Time.deltaTime);
}
void OnCollisionEnter(Collision col)
{
if (IsInLayerMask(col.gameObject, groundMask))
{
playerVelocity.y = 0f;
_animator.SetBool("Jumping", false);
}
}
private bool IsInLayerMask(GameObject obj, LayerMask layerMask)
{
return ((layerMask.value & (1 << obj.layer)) > 0);
}
public void playStoneStep()
{
_audioSource.PlayOneShot(_stepStone);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour
{
[SerializeField] Transform playerCamera = null;
[SerializeField] float xSensitivity = 4.0f;
[SerializeField] float ySensitivity = 4.0f;
[SerializeField] float moveSpeed = 6.0f;
[SerializeField] float gravity = -13.0f;
[SerializeField][Range(0.0f, 0.1f)] float moveSmoothTime = 0.05f;
[SerializeField][Range(0.0f, 0.2f)] float mouseSmoothTime = 0.03f;
[SerializeField] bool lockCursor = true;
float cameraPitch = 0.0f;
float velocityY = 0.0f;
CharacterController controller = null;
Vector2 currentDir = Vector2.zero;
Vector2 currentDirVelocity = Vector2.zero;
Vector2 currentMouseDelta = Vector2.zero;
Vector2 currentMouseDeltaVelocity = Vector2.zero;
public Vector3 jump;
public float jumpForce = 8.0f;
public bool isGrounded;
Rigidbody rb;
void Start()
{
rb = GetComponent<Rigidbody>();
jump = new Vector3(0.0f, 2.0f, 0.0f);
controller = GetComponent<CharacterController>();
if(lockCursor)
{
Cursor.lockState = CursorLockMode.Locked;
Cursor.visible = false;
}
}
// Update is called once per frame
void Update()
{
UpdateMouseLook();
UpdateMovement();
OnCollisionStay();
UpdateJump();
}
void UpdateMouseLook()
{
Vector2 targetMouseDelta = new Vector2(Input.GetAxis("Mouse X"), Input.GetAxis("Mouse Y"));
currentMouseDelta = Vector2.SmoothDamp(currentMouseDelta, targetMouseDelta, ref currentMouseDeltaVelocity, mouseSmoothTime);
cameraPitch -= currentMouseDelta.y * ySensitivity;
cameraPitch = Mathf.Clamp(cameraPitch, -70.0f, 70.0f);
playerCamera.localEulerAngles = Vector3.right * cameraPitch;
transform.Rotate(Vector3.up * currentMouseDelta.x * xSensitivity);
}
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 = 0.0f;
velocityY += gravity * Time.deltaTime;
Vector3 velocity = (transform.forward * currentDir.y + transform.right * currentDir.x) * moveSpeed + Vector3.up * velocityY;
controller.Move(velocity * Time.deltaTime);
}
void OnCollisionStay()
{
isGrounded = true;
}
void UpdateJump()
{
if (Input.GetKeyDown(KeyCode.Space) && isGrounded)
{
rb.AddForce(jump * jumpForce, ForceMode.Impulse);
isGrounded = false;
Debug.Log("JUMP");
}
}
}
In my script I can't seem to get the UpdateJump function to work as intended. When I press space I get the console message but the rb.AddForce appears to do nothing. what is the reason that I can't get my player controller to jump and how can I go about fixing this and making sure it doesn't occur again further down the line.
Hello I am trying to move a game object in 3d space I have searched the internet and found there are 3 ways to do that using turntoface(euler angles) or quaternion or navmesh agents
My problem is the game object default rotation is changing in using quaternions or move towards.
Can anyone help me understand why it is happening like that.
I want the capsule in slanted position.
//below code is using quaternions
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Guard : MonoBehaviour
{
public float speed = 5;
public float waitTime = .3f;
public float turnSpeed = 90;
public Transform pathHolder;
public Transform target;
void Start()
{
Vector3[] waypoints = new Vector3[pathHolder.childCount];
for (int i = 0; i < waypoints.Length; i++)
{
waypoints = pathHolder.GetChild(i).position;
waypoints = new Vector3(waypoints.x, transform.position.y, waypoints.z);
}
StartCoroutine(FollowPath(waypoints));
}
IEnumerator FollowPath(Vector3[] waypoints)
{
transform.position = waypoints[0];
int targetWaypointIndex = 1;
Vector3 targetWaypoint = waypoints[targetWaypointIndex];
while (true)
{
Quaternion targetRotation = Quaternion.LookRotation(targetWaypoint - transform.position);
transform.rotation = Quaternion.RotateTowards(transform.rotation, targetRotation, turnSpeed * Time.deltaTime);
if (transform.rotation == targetRotation)
{
transform.position = Vector3.MoveTowards(transform.position, targetWaypoint, speed * Time.deltaTime);
if (transform.position == targetWaypoint)
{
targetWaypointIndex = (targetWaypointIndex + 1) % waypoints.Length;
targetWaypoint = waypoints[targetWaypointIndex];
yield return new WaitForSeconds(waitTime);
}
}
yield return null;
}
IEnumerator TurnToFace(Vector3 lookTarget)
{
Vector3 dirToLookTarget = (lookTarget - transform.position).normalized;
float targetAngle = 90 - Mathf.Atan2(dirToLookTarget.y, dirToLookTarget.x) * Mathf.Rad2Deg;
while (Mathf.Abs(Mathf.DeltaAngle(transform.eulerAngles.y, targetAngle)) > 0.05f)
{
float angle = Mathf.MoveTowardsAngle(transform.eulerAngles.y, targetAngle, turnSpeed * Time.deltaTime);
transform.eulerAngles = Vector3.up * angle;
yield return null;
}
}
void OnDrawGizmos()
{
Vector3 startPosition = pathHolder.GetChild(0).position;
Vector3 previousPosition = startPosition;
foreach (Transform waypoint in pathHolder)
{
Gizmos.DrawSphere(waypoint.position, .3f);
Gizmos.DrawLine(previousPosition, waypoint.position);
previousPosition = waypoint.position;
}
Gizmos.DrawLine(previousPosition, startPosition);
}
}
}
//below code is using turntoface (euler angles concept)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Guard : MonoBehaviour
{
public float speed = 5;
public float waitTime = .3f;
public float turnSpeed = 90;
public Transform pathHolder;
void Start()
{
Vector3[] waypoints = new Vector3[pathHolder.childCount];
for (int i = 0; i < waypoints.Length; i++)
{
waypoints = pathHolder.GetChild(i).position;
waypoints = new Vector3(waypoints.x, transform.position.y, waypoints.z);
}
StartCoroutine(FollowPath(waypoints));
}
IEnumerator FollowPath(Vector3[] waypoints)
{
transform.position = waypoints[0];
int targetWaypointIndex = 1;
Vector3 targetWaypoint = waypoints[targetWaypointIndex];
transform.LookAt(targetWaypoint);
while (true)
{
transform.position = Vector3.MoveTowards(transform.position, targetWaypoint, speed * Time.deltaTime);
if (transform.position == targetWaypoint)
{
targetWaypointIndex = (targetWaypointIndex + 1) % waypoints.Length;
targetWaypoint = waypoints[targetWaypointIndex];
yield return new WaitForSeconds(waitTime);
yield return StartCoroutine(TurnToFace(targetWaypoint));
}
yield return null;
}
}
IEnumerator TurnToFace(Vector3 lookTarget)
{
Vector3 dirToLookTarget = (lookTarget - transform.position).normalized;
float targetAngle = 90 - Mathf.Atan2(dirToLookTarget.z, dirToLookTarget.x) * Mathf.Rad2Deg;
while (Mathf.DeltaAngle(transform.eulerAngles.y, targetAngle) > 0.05f)
{
float angle = Mathf.MoveTowardsAngle(transform.eulerAngles.y, targetAngle, turnSpeed * Time.deltaTime);
transform.eulerAngles = Vector3.up * angle;
yield return null;
}
}
void OnDrawGizmos()
{
Vector3 startPosition = pathHolder.GetChild(0).position;
Vector3 previousPosition = startPosition;
foreach (Transform waypoint in pathHolder)
{
Gizmos.DrawSphere(waypoint.position, .3f);
Gizmos.DrawLine(previousPosition, waypoint.position);
previousPosition = waypoint.position;
}
Gizmos.DrawLine(previousPosition, startPosition);
}
}
This link has all videos and required output for reference
I'm using the mouse for looking around and it is working properly when looking up and down, but when looking left or right it moves really slow and it has jittery movement. I don't see why.
Here is my Movement class:
public class Movement : MonoBehaviour
{
[SerializeField] CharacterController controller;
[SerializeField] float speed = 15f;
Vector2 horizontalInput;
[SerializeField] float jumpHeight = 3.5f;
bool jump;
[SerializeField] float gravity = -30f; //-9.81
Vector3 verticalVelocity = Vector3.zero;
[SerializeField] LayerMask groundMask;
bool isGrounded;
private void Update()
{
isGrounded = Physics.CheckSphere(transform.position, 0.1f, groundMask);
if (isGrounded)
{
verticalVelocity.y = 0;
}
Vector3 horizontalVelocity = (transform.right * horizontalInput.x + transform.forward *
horizontalInput.y ) * speed;
controller.Move(horizontalVelocity * Time.deltaTime);
// Jump: v = sqrt(-2 * jumpheight* gravity)
if (jump)
{
if (isGrounded)
{
verticalVelocity.y = Mathf.Sqrt(-2f * jumpHeight * gravity);
}
jump = false;
}
verticalVelocity.y += gravity * Time.deltaTime;
controller.Move(verticalVelocity * Time.deltaTime);
}
public void ReceiveInput(Vector2 _horizontalInput)
{
horizontalInput = _horizontalInput;
}
public void OnJumpPressed()
{
jump = true;
}
}
MouseLook class:
public class MouseLook : MonoBehaviour
{
[SerializeField] float sensitivityX = 8f;
[SerializeField] float sensitivityY = 0.5f;
float mouseX, mouseY;
[SerializeField] Transform playerCamera;
[SerializeField] float xClamp = 85f;
float xRotataion = 0f;
private void Update()
{
transform.Rotate(Vector3.up, mouseX * Time.deltaTime);
xRotataion -= mouseY;
xRotataion = Mathf.Clamp(xRotataion, -xClamp, xClamp);
Vector3 targetRotation = transform.eulerAngles;
targetRotation.x = xRotataion;
playerCamera.eulerAngles = targetRotation;
}
public void ReceiveInput(Vector2 mouseInput)
{
mouseX = mouseInput.x * sensitivityX;
mouseY = mouseInput.y * sensitivityY;
}
}
Because I'm using the new input system here is my InputManager class:
public class InputManager : MonoBehaviour
{
[SerializeField] Movement movement;
[SerializeField] MouseLook mouseLook;
PlayerControls controls;
PlayerControls.GroundMovementActions groundMovement;
Vector2 horizontalInput;
Vector2 mouseInput;
private void Awake()
{
controls = new PlayerControls();
groundMovement = controls.GroundMovement;
// groundMovement.[action].performed += context => do something
groundMovement.HorizontalMovement.performed += ctx => horizontalInput = ctx.ReadValue<Vector2>();
groundMovement.Jump.performed += _ => movement.OnJumpPressed();
groundMovement.MouseX.performed += ctx => mouseInput.x = ctx.ReadValue<float>();
groundMovement.MouseY.performed += ctx => mouseInput.y = ctx.ReadValue<float>();
}
private void Update()
{
movement.ReceiveInput(horizontalInput);
mouseLook.ReceiveInput(mouseInput);
}
private void OnEnable()
{
controls.Enable();
}
private void OnDestroy()
{
controls.Disable();
}
}
I tried setting sensitivityX to a larger number but the jitter effect is still there.
How would I fix that and make it smooth?
I have a simple script to move and look around when I turn the camera doesn't turn with the character how do I make them turn together.
using System.Collections.Generic;
using UnityEngine;
public class PlayerFollow : MonoBehaviour
{
public Transform PlayerTransform;
private Vector3 _cameraOffset;
public float rotationSpeed = 1;
public Transform Target, Player;
float mouseX, mouseY;
[Range(0.01f, 1.0f)]
public float SmoothFactor = 0.5f;
public bool LookAtPlayer = false;
// Start is called before the first frame update
void Start()
{
_cameraOffset = transform.position - PlayerTransform.position;
Cursor.visible = false;
Cursor.lockState = CursorLockMode.Locked;
}
// Update is called once per frame
void LateUpdate()
{
CamControl();
Vector3 newPos = PlayerTransform.position + _cameraOffset;
transform.position = Vector3.Slerp(transform.position, newPos, SmoothFactor);
/*if(LookAtPlayer){
transform.LookAt(PlayerTransform);
}*/
}
void CamControl()
{
mouseX += Input.GetAxis("Mouse X") * rotationSpeed;
mouseY += Input.GetAxis("Mouse Y") * rotationSpeed * -1;
mouseY = Mathf.Clamp(mouseY, -35, 60);
transform.LookAt(Target);
Target.rotation = Quaternion.Euler(mouseY, mouseX, 0);
Player.rotation = Quaternion.Euler(0, mouseX, 0);
}
}
[Picture Of Workspace]
I think You should make the camera child of the player and then attach this code to the player.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
public CharacterController characterController;
public float speed;
private Vector3 camRotation;
private Transform cam;
private Vector3 moveDirection;
[Range(-45, -15)]
public int minAngle = -30;
[Range(30, 80)]
public int maxAngle = 45;
[Range(50, 500)]
public int sensitivity = 200;
private void Awake()
{
cam = Camera.main.transform;
}
void Update()
{
Move();
Rotate();
}
private void Rotate()
{
transform.Rotate(Vector3.up * sensitivity * Time.deltaTime * Input.GetAxis("Mouse X"));
camRotation.x -= Input.GetAxis("Mouse Y") * sensitivity * Time.deltaTime;
camRotation.x = Mathf.Clamp(camRotation.x, minAngle, maxAngle);
cam.localEulerAngles = camRotation;
}
private void Move()
{
float horizontalMove = Input.GetAxis("Horizontal");
float verticalMove = Input.GetAxis("Vertical");
if (characterController.isGrounded)
{
moveDirection = new Vector3(horizontalMove, 0, verticalMove);
moveDirection = transform.TransformDirection(moveDirection);
}
moveDirection.y -= gravity * Time.deltaTime;
characterController.Move(moveDirection * speed * Time.deltaTime);
}
}
Please do not forget to add a Character Controller to the player, and then assign it in the inspector.