Adding additional vertical velocity in projectile motion Unity3D - c#

I have my point of projectile at some height above ground and my enemy(that are moving from right to left and towards the shooting point at horizontal axis) are at ground.The projectile motion that I have it shoots directly in downward motion at angle facing the enemy but I want the projectile to first go upwards and then shoot the enemy.
I have attached the snapshot below:
Here is my code:
using UnityEngine;
using System.Collections;
public class bullet : MonoBehaviour {
public Transform target;
private Transform mytransform;
public GameObject bulletprefab;
public GameObject enemyprefab;
private gamenemy e;
public float firingAngle = 20;
public float gravity = 9.8f;
void Awake()
{
mytransform = transform;
}
// Use this for initialization
void Start () {
mytransform.LookAt(target);
StartCoroutine (project ());
//follow();
}
IEnumerator project()
{ yield return new WaitForSeconds(0.25f);
float target_Distance = Vector3.Distance(mytransform.position * target_Distance , target.position);
// Calculate the velocity needed to throw the object to the target at specified angle.
float projectile_Velocity = target_Distance / (Mathf.Sin(2 * target_Distance * Mathf.Deg2Rad) / gravity);
// Extract the X Y componenent of the velocity
float Vx = Mathf.Sqrt(projectile_Velocity) * Mathf.Cos(target_Distance * Mathf.Deg2Rad);
float Vy = Mathf.Sqrt(projectile_Velocity) * Mathf.Sin( 1/target_Distance * Mathf.Deg2Rad);
// Calculate flight time.
float flightDuration = target_Distance / Vx;
// Rotate projectile to face the target.
mytransform.rotation = Quaternion.LookRotation(target.position - mytransform.position);
float elapse_time = 0;
while (elapse_time < flightDuration)
{
mytransform.Translate(0, (Vy - (gravity * elapse_time)) * Time.deltaTime, Vx * Time.deltaTime);
elapse_time += Time.deltaTime;
yield return null;
}
}
Snapshot of how it is with given code:
This is how I want it to be:

Rather than calculating the movement in your code, look at using a Rigidbody on your projectile. Then at the point of firing, apply a force relative to the initial trajectory (i.e direction the gun barrel is facing) and also have gravity affect your bullet.
More on Rigidbodies

Related

How to make the player move according to the camera motion

Now I'm a beginner game developer and I'm working on a game so I have set the camera motion that when you move the mouse the player rotates however I want to make the WASD keys work to the direction the player is rotated. Basically when I rotate the camera to the left the W key still moves the player on the Z dimension. How can I fix this?
Here's my player rotation code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraMovement : MonoBehaviour
{
public float speedH = 2.0f;
public float speedV = 2.0f;
private float yaw = 0.0f;
private float pitch = 0.0f;
// Use this for initialization
void Start()
{
}
// Update is called once per frame
void Update()
{
yaw += speedH * Input.GetAxis("Mouse X");
pitch -= speedV * Input.GetAxis("Mouse Y");
transform.eulerAngles = new Vector3(pitch, yaw, 0.0f);
}
}
Moving in the direction the character is facing is a simple work for Transform.forward and Transform.right because you need to move the player based on local position and rotation and not the world one.
For example, you could have
void Move (float h, float v)
{
movement.Set (h, 0f, v);
movement = movement.normalized * speed * Time.deltaTime;
playerRigidbody.MovePosition (transform.position + (transform.forward * movement.z) + (transform.right * movement.x));
}
The Rigidbody is what you need to move it, if you want an object that is always moving in the direction is facing you could easily do a
transform.position += transform.forward * Time.deltaTime * movementSpeed;
In this case, to go back you should subtract instead of add.
But use my first suggestion for your player :D
EDIT
In your update you can add
Move(yaw, pitch);

Rotate rigidbody with moverotation in the direction of the camera

I want to use moverotation to rotate the object in the direction of the Main Camera, like a common third person shooter, but I don't know how to set the quaternion values or otherwise
`using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class movimento : MonoBehaviour
{
[SerializeField] float walk = 1;
[SerializeField] float run = 2;
Vector3 movement = Vector3.zero;
private Rigidbody rig;
// Start is called before the first frame update
void Start()
{
rig = GetComponent<Rigidbody>();
}
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown(KeyCode.LeftShift)) walk = (walk + run);
if (Input.GetKeyUp(KeyCode.LeftShift)) walk = (walk - run);
float Horizontal = Input.GetAxis("Horizontal");.
float Vertical = Input.GetAxis("Vertical");
movement = Camera.main.transform.forward * Vertical + Camera.main.transform.right * Horizontal;
float origMagnitude = movement.magnitude;
movement.y = 0f;
movement = movement.normalized * origMagnitude;
}
private void FixedUpdate ()
{
rig.MovePosition(rig.position + movement * walk * Time.fixedDeltaTime);
Quaternion rotation = Quaternion.Euler(???);
rig.MoveRotation(rig.rotation * rotation);
}
}`
i use a coroutine to do smooth rotation. I use Quaternion.LookRotation for the job.
so you indicate the position of object to look at and the duration of animation. Here you want to rotate face to the main camera
StartCoroutine(SmoothRotation(Camera.main.transform, 3f));
:
:
IEnumerator SmoothRotation(Transform target, float duration)
{
float currentDelta = 0;
var startrotation = transform.rotation;//use your rigisbody if you want here i use the gameobject
var LookPos = target.position - transform.position;
var finalrot = Quaternion.LookRotation(LookPos);
while (currentDelta <= 1f)
{
currentDelta += Time.deltaTime / duration;
transform.rotation = Quaternion.Lerp(startrotation, finalrot, currentDelta);//
yield return null;
}
transform.rotation = finalrot;
}
if you want to see (in scene when running) where your camera points just add this line of code in update():
Debug.DrawRay(Camera.main.transform.position, Camera.main.transform.TransformDirection(Vector3.forward) * 10f, Color.black);
if you want to point in same direction tha nthe Camera just change the line of finalrot in SmoothRotation Method:
var finalrot = Camera.main.transform.rotation;
you dont need to calculate the LookPos
for your problem of crazy rotation, i suggest you to reset rotation x and z
direction = hit.transform.position - transform.position;
Quaternion rotation = Quaternion.LookRotation(direction);
rotation.x = 0f;
rotation.z = 0f;
a tips to detect object what you want with the raycast inside spere : Physics.OverlapSphere: you could select what you want to cast when using the optional parameter layermask
private void DetectEnemy(Vector3 center, float radius)
{
var hitColliders = Physics.OverlapSphere(center, radius );
for (var i = 0; i < hitColliders.Length; i++)
{
print(hitColliders[i].name + "," + hitColliders[i].transform.position);
// collect information on the hits here
}
}
I created a raycast from the camera, and I would like to rotate the rigidbody to where the raycast is pointing but if i launch unity, it rotated wildly. What is the error?
Vector3 direction;
Vector3 rayDir = new Vector3(Screen.width/2,Screen.height/2);
void Update()
Ray ray = Camera.main.ScreenPointToRay(rayDir);
Debug.DrawRay(ray.origin, ray.direction * 10, Color.yellow);
RaycastHit hit = new RaycastHit ();
direction = hit.point - transform.position;
private void FixedUpdate ()
Quaternion rotation = Quaternion.LookRotation(direction);
rig.MoveRotation(rig.rotation * rotation);
Add a character controller component, this is what is for. See:
https://docs.unity3d.com/Manual/class-CharacterController.html

Unity Rotation of Parent object along 1 Axis

I'm working on developing a game, and my current roadblock is Camera Rotation. I want the mouse to control the camera, and when the camera turns, I want to rotate the player as well. However, the code I am using rotates the player object COMPLETELY with the player, causing the player to turn like this:
The player rotating forward not only looks strange, but causes clipping problems with the terrain. How do I make my code only rotate the player along one axis, while allowing the camera to rotate along any axis (to allow the audience to look around, without the player object being turned upwards or down).
this is the code that is rotating the player:
Quaternion QT = Quaternion.Euler(_LocalRotation.y, _LocalRotation.x, 0);
this._XForm_Parent.rotation = Quaternion.Lerp(this._XForm_Parent.rotation, QT, Time.deltaTime * OrbitDampening);
if (this._XForm_Camera.localPosition.z != this._CameraDistance * -1f)
{
this._XForm_Camera.localPosition = new Vector3(0f, 0f, Mathf.Lerp(this._XForm_Camera.localPosition.z, this._CameraDistance * -1f, Time.deltaTime * ScrollDampening));
}
and this is the complete script I am using:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraOrbit : MonoBehaviour
{
protected Transform _XForm_Camera;
protected Transform _XForm_Parent;
protected Vector3 _LocalRotation;
protected float _CameraDistance = 10f;
public float MouseSensitivity = 4f;
public float ScrollSensitvity = 2f;
public float OrbitDampening = 10f;
public float ScrollDampening = 6f;
public bool CameraDisabled = false;
// Use this for initialization
void Start()
{
this._XForm_Camera = this.transform;
this._XForm_Parent = this.transform.parent;
}
void LateUpdate()
{
if (Input.GetKeyDown(KeyCode.LeftShift))
CameraDisabled = !CameraDisabled;
if (!CameraDisabled)
{
//Rotation of the Camera based on Mouse Coordinates
if (Input.GetAxis("Mouse X") != 0 || Input.GetAxis("Mouse Y") != 0)
{
_LocalRotation.x += Input.GetAxis("Mouse X") * MouseSensitivity;
_LocalRotation.y += Input.GetAxis("Mouse Y") * MouseSensitivity;
//Clamp the y Rotation to horizon and not flipping over at the top
if (_LocalRotation.y < 0f)
_LocalRotation.y = 0f;
else if (_LocalRotation.y > 90f)
_LocalRotation.y = 90f;
}
//Zooming Input from our Mouse Scroll Wheel
if (Input.GetAxis("Mouse ScrollWheel") != 0f)
{
float ScrollAmount = Input.GetAxis("Mouse ScrollWheel") * ScrollSensitvity;
ScrollAmount *= (this._CameraDistance * 0.3f);
this._CameraDistance += ScrollAmount * -1f;
this._CameraDistance = Mathf.Clamp(this._CameraDistance, 1.5f, 100f);
}
}
//Actual Camera Rig Transformations
Quaternion QT = Quaternion.Euler(_LocalRotation.y, _LocalRotation.x, 0);
this._XForm_Parent.rotation = Quaternion.Lerp(this._XForm_Parent.rotation, QT, Time.deltaTime * OrbitDampening);
if (this._XForm_Camera.localPosition.z != this._CameraDistance * -1f)
{
this._XForm_Camera.localPosition = new Vector3(0f, 0f, Mathf.Lerp(this._XForm_Camera.localPosition.z, this._CameraDistance * -1f, Time.deltaTime * ScrollDampening));
}
}
}
A picture of my heirarchy:
(Please note that Player is an empty object containing all of my scripts and physics components, whereas the GFXs component is simply the model, with an animator component clean of any physics components.)
It sounds like what you want is basically to rotate the player around its local Y axis until it is facing the same direction as the camera. You can find out if things are facing the same direction using Vector3.SignedAngle and passing in the axis that you care about. Here is some sample code that should get you going.
float turnThresholdDegrees = 15;
float playerTurnSpeed = 1;
// Get delta angle in degrees on the Y axis between the direction player is facing and the direction camera is facing
float angleDelta = Vector3.SignedAngle(player.transform.forward, camera.transform.forward, Vector3.up);
// Calculate a rotation speed, clamping it to 0 when the angle delta is < some threshold
float rotateSpeed = Mathf.Abs(angleDelta) > turnThresholdDegrees ? Mathf.Sign(angleDelta) * playerTurnSpeed : 0;
// Rotate the player around its local Y axis by the rotation speed
player.transform.Rotate(0, rotateSpeed * Time.deltaTime, 0, Space.Self);

Moving player horizontally while in lerp jump Unity C#

The code I have allows a player object to move around the circumference of a circle and then "jump" to the center of that circle.
What I am trying to do is allow the player to continue their movement around the circle while jumping so that the player can alter their position while jumping.
This is the full code I have so far.
using UnityEngine;
using System.Collections;
public class Movement : MonoBehaviour
{
//editable property if made public
public float playerSpeed = 20f;//This is how fast the player moves
float playerAngle = 0; //This is the players movement variable
float radius = 4f; //This is the radius of how big the circle is (Circumference track 2piRadius
float startTime; //This is the time the game started
float gameTime; //This will be player points BASE THIS OFF OF HOW LONG THE GAMES RUNNING
float playerRadius = .5f; //CHANGE TO THE PLAYER OBJECT VARIABLE, is how offset the player will be from the lvlradius.
private bool jumping = false; //This effects movement during the game
private Vector3 playerPosition; //This is the playerPosition in the game
void Start()
{
//Called at the start of the game
}
void Update()
{
if (jumping)
{
return;
}
else if (Input.GetKey(KeyCode.LeftArrow) || Input.GetKey(KeyCode.RightArrow))
{
circularMove();
}
else if (Input.GetKeyDown(KeyCode.Space))
{
StartCoroutine(jumpPlayer());
}
}
void FixedUpdate()
{
//Called before performing physics calculations
}
void circularMove()
{
//player variables
//The angle the player is at is equal to the speed of the player divided by radius times time in the game and the addition of the left right keys
playerAngle += Input.GetAxis("Horizontal") * Time.deltaTime * (playerSpeed / radius);
//This is the movement on the x axis
float x = Mathf.Cos(playerAngle) * (radius - playerRadius);
//this is the movement on the y axis
float y = Mathf.Sin(playerAngle) * (radius - playerRadius);
//the player does not move forward at this time THIS WILL BE HOW TO MOVE THE PLAYER
float z = 0;
//move the player in the direction that they clicked but add the original coordinates to the players location
transform.position = new Vector3(x, y, z);
//Move the player;
playerPosition = transform.position;
}
private IEnumerator jumpPlayer()
{
Vector3 playerEndPos = new Vector3(0f, 0f, 0f);
Vector3 playerStartPos = playerPosition;
float i = 0.0f;
float rate = .1f / Time.deltaTime;
jumping = true;
while (i< 1.0)
{
i += Time.deltaTime * rate;
transform.position = Vector3.Lerp(playerStartPos, playerEndPos, i);
yield return null;
}
transform.position = playerEndPos;
i = 0.0f;
while (i < 1.0)
{
i += Time.deltaTime * rate;
transform.position = Vector3.Lerp(playerEndPos, playerStartPos, i);
yield return null;
}
transform.position = playerStartPos;
jumping = false;
yield break;
}
}
With the current Update your idea will never be possible, because if a user is jumping, you are ignoring the input of the left and right key.
By shifting the if(jumping) to the actual jump statement you could probably bypass this.
void Update()
{
if (Input.GetKey(KeyCode.LeftArrow) || Input.GetKey(KeyCode.RightArrow))
{
circularMove();
}
else if (Input.GetKeyDown(KeyCode.Space))
{
if (!jumping)
StartCoroutine(jumpPlayer());
}
}

Unity2D Smooth Rotation using Slerp

I'm making a patrol script for a game object. I want the object to rotate smoothly and slowly to face it's patrol target.
Unfortunately, the object snaps to it's new location.
I've asked on unity forums and can't get an answer.
How can I get the rotation to be smooth and slow?
Here's my code.
public Transform[] patrol;
public int Currentpoint;
public float moveSpeed;
public Vector3 john = new Vector3(0,1,0);
public Vector3 targetLocation;
void Start()
{
}
void Update()
{
if (transform.position == patrol [Currentpoint].position) {
Currentpoint++;
if (Currentpoint >= patrol.Length) {
Currentpoint = 0;
}
targetLocation = patrol [Currentpoint].position;
Vector3 targetDir = targetLocation - transform.position;
float angle = Mathf.Atan2 (targetDir.y, targetDir.x) * Mathf.Rad2Deg;
transform.localRotation = Quaternion.SlerpUnclamped (transform.localRotation, Quaternion.AngleAxis (angle, Vector3.forward), Time.deltaTime * 3);
Debug.Log (Currentpoint);
}
transform.position = Vector3.MoveTowards (transform.position, patrol [Currentpoint].position, moveSpeed * Time.deltaTime);
}
public static Quaternion Slerp(Quaternion a, Quaternion b, float t); The parameter t is clamped to the range [0, 1]
your times 3 is throwing it out so it is not between 0-1 ... I believe
If you like some mathematics then I have a solution for you.
You want to rotate object around another, like Earth and Sun. May be some other solutions may available but I would do it through LookAt and parametric equation of circle.
x = r * cos(theta) + displacementX
y = r * sin(theta) + displacementY
where r is radius, distance in your case
displacementX and displacementY are the distance from origin. If both (displacementX and displacementY) is 0 then it will rotate around origin (0,0). In other words displacementX and displacementY is the origin of rotation.
In Object(Earth) script, do it as follow
public Transform _sun;
float _theta = 0;
void Start ()
{
StartCoroutine ("ChangeAngle");
}
void Update ()
{
transform.LookAt (_sun);
float newX = (5 * Mathf.Cos (_theta)) + _sun.position.x;
float newY = (5 * Mathf.Sin (_theta)) + _sun.position.y;
transform.position = new Vector3 (newX, newY, _sun.position.z);
}
IEnumerator ChangeAngle ()
{
while (true) {
yield return new WaitForSeconds (0.01f);
_theta += 0.1f;
if (_theta >= 360)
_theta = 0;
}
}
You can further play with it
I found an answer,
It turns out that placing the rotational instructions within the if statement was the problem. I converted the rotation to a function, then placed the function above the general patrol movement in the same loop segment.
I don't know why it worked.
Thanks to everyone for their help.

Categories