Bullet instantiation angle is wrong when the player rotates - c#

I created a projectile bullet effect with 3 different instantiation positions. It works perfectly while the player is facing right. But when facing left the angle of the bullet instantiation goes astray. Any help is appreciated.
Screenshot of when the player is turning right.
Screenshot of when the player is turning left.
The code of the player.
private IEnumerator FireContinuously()
{
while (true)
{
GameObject laser02 = Instantiate(bullet01, firePoint2.position, Quaternion.Euler(new Vector3(0, 0, 10)));
laser02.GetComponent<Rigidbody2D>().velocity = laser02.transform.right * projectileSpeed * direction;
GameObject laser03 = Instantiate(bullet02, firePoint.position, Quaternion.Euler(new Vector3(0, 0, 0)));
laser03.GetComponent<Rigidbody2D>().velocity = laser03.transform.right * projectileSpeed * direction;
GameObject laser04 = Instantiate(bullet03, firePoint3.position, Quaternion.Euler(new Vector3(0, 0, 345)));
laser04.GetComponent<Rigidbody2D>().velocity = laser04.transform.right * projectileSpeed * direction;
yield return new WaitForSeconds(projectileFiringPeriod);
}
}
public void Flipsprite()
{
bool playerhashorizontalspeed = Mathf.Abs(myRigidBody.velocity.x) > 0;
if (playerhashorizontalspeed)
{
direction = Mathf.Sign(myRigidBody.velocity.x);
transform.localScale = new Vector3(direction, 1f);
}
}

You are using hardcoded angles 10 and 345 regardless the direction you are looking.
Then using e.g. laser02.right always returns the same Vector3 only that you negate it. That results in an incorrect direction. It is the direction you get if you compare the images.
What you rather want is to negate also the angle by which you rotated the bullets.
private IEnumerator FireContinuously()
{
while (true)
{
var laser02 = Instantiate(bullet01, firePoint2.position, Quaternion.Euler(new Vector3(0, 0, 10 * direction)));
laser02.GetComponent<Rigidbody2D>().velocity = laser02.transform.right * projectileSpeed * direction;
var laser03 = Instantiate(bullet02, firePoint.position, Quaternion.Identity)
laser03.GetComponent<Rigidbody2D>().velocity = laser03.transform.right * projectileSpeed * direction;
var laser04 = Instantiate(bullet03, firePoint3.position, Quaternion.Euler(new Vector3(0, 0, 345 * direction)));
laser04.GetComponent<Rigidbody2D>().velocity = laser04.transform.right * projectileSpeed * direction;
yield return new WaitForSeconds(projectileFiringPeriod);
}
}
And a little hint:
If you would rather make your prefabs of type
[SerializeField] private RigidBody2D bullet01;
[SerializeField] private RigidBody2D bullet02;
[SerializeField] private RigidBody2D bullet03;
then Instantiate would directly return the according RigidBody2D reference and you could get rid of the GetComponent calls:
private IEnumerator FireContinuously()
{
while (true)
{
var laser02 = Instantiate(bullet01, firePoint2.position, Quaternion.Euler(new Vector3(0, 0, 10 * direction)));
laser02.velocity = laser02.transform.right * projectileSpeed * direction;
var laser03 = Instantiate(bullet02, firePoint.position, Quaternion.Identity)
laser03.velocity = laser03.transform.right * projectileSpeed * direction;
var laser04 = Instantiate(bullet03, firePoint3.position, Quaternion.Euler(new Vector3(0, 0, 345 * direction)));
laser04.velocity = laser04.transform.right * projectileSpeed * direction;
yield return new WaitForSeconds(projectileFiringPeriod);
}
}

Related

Simultaneous processing of moving and rotating objects

It has a similar feeling, but this code keeps following the player.
private void FixedUpdate()
{
Vector3 playerPos = _player.transform.position;
Vector3 dirVec = playerPos - transform.position;
dirVec = dirVec.normalized;
transform.Translate(dirVec * 1f * Time.fixedDeltaTime,Space.World);
transform.Rotate(0, 0, -Time.fixedDeltaTime * speed);
}
How can I implement it only in the direction of the player and not follow it?
use transorfm.lookAt() for simple direction following:
void FixedUpdate()
{
transform.LookAt(_player.transform, Vector3.up);
}
For smooth following:
public float rotateTime = 1f; // must not be zero
private void FixedUpdate()
{
var dirVec = _player.transform.position - transform.position;
var lookRotation = Quaternion.LookRotation(dirVec);
transform.rotation = Quaternion.Slerp(transform.rotation, lookRotation, Time.fixedDeltaTime/rotateTime);
}

Unity2d Shoot Ball From Cannon at Z Rotation

I have the cannon attached to a hinge2d.
I move it by the Z rotation.
float offset = Mathf.Abs(gameObject.transform.eulerAngles.z);
if (Input.GetKey("w"))
{
gun.transform.rotation = Quaternion.RotateTowards(
gun.transform.rotation,
Quaternion.Euler(0.0f, 0.0f, minClamp + offset),
rotationSpeed * Time.deltaTime);
}
else if (Input.GetKey("s"))
{
gun.transform.rotation = Quaternion.RotateTowards(
gun.transform.rotation,
Quaternion.Euler(0.0f, 0.0f, maxClamp + offset),
rotationSpeed * Time.deltaTime);
}
This code has an offset for Z-rotation of any object the the cannon is mounted on.
When the cannon is fully up, I have it constrained to Z = 30.
When the cannon is fully down, I have it constrained to Z = -60.
What I'm trying to do is shoot the cannon ball out and up based on where the cannon is pointing.
I have tried a few different things, all of which didn't work.
private void ShootBullet()
{
GameObject bullet = Instantiate(bulletPrefab, gunTip.transform.position, Quaternion.identity);
var rb = bullet.GetComponent<Rigidbody2D>();
//setting rotation of bullet to have same rotation of cannon stem
bullet.transform.rotation = Quaternion.Euler(
gun.transform.eulerAngles.x,
gun.transform.eulerAngles.y,
gun.transform.eulerAngles.z + Mathf.Abs(gameObject.transform.eulerAngles.z));
//this is my issue right now, I dont know how to apply the correct force to the Y direction based on the Z(angle) of my cannon.
rb.AddForce(new Vector3( bulletSpeed, ?, 0), ForceMode2D.Impulse);
}
I have found some code snippet which may help you.
void Launch() {
GameObject clone = Instantiate (projectile, shootLocation, Quaternion.identity) as GameObject;
Rigidbody2D clonerb = clone.GetComponent<Rigidbody2D> ();
clonerb.AddRelativeForce (
transform.TransformDirection(new Vector2(
(Mathf.Cos (transform.rotation.z * Mathf.Deg2Rad) * speed),
(Mathf.Sin (transform.rotation.z * Mathf.Deg2Rad) * speed) )
),
ForceMode2D.Impulse
);
}
Source: 1
Further more an Setup that I created just now and worked is following:
public class Shoot : MonoBehaviour {
public GameObject Bullet;
public Transform ShootPoint;
public float bulletSpeed = 10.0f;
void Start() {
}
// Update is called once per frame
void Update() {
if(Input.GetKeyDown(KeyCode.Space)) {
if(!Bullet)
return;
GameObject clone = Instantiate(Bullet, ShootPoint.position, ShootPoint.rotation);
Rigidbody2D rb2d = clone.GetComponent<Rigidbody2D>();
rb2d.AddRelativeForce(Vector2.right * bulletSpeed, ForceMode2D.Impulse);
}
}
}
You could rather simply use AddRelativeForce
Adds a force to the rigidbody2D relative to its coordinate system.
which takes the orientation of the object into account:
// You should also simply set the rotation vis the Rigidbody2D component
rb.rotation = gunTip.transform.eulerAngles.z;
rb.AddRelstiveForce(Vector2.right * bulletSpeed, ForceMode2D.Impulse);
This ended up being what I needed. Thanks #At Least Vision
private void ShootBullet()
{
GameObject bullet = Instantiate(bulletPrefab, gunTip.transform.position, Quaternion.identity);
var rb = bullet.GetComponent<Rigidbody2D>();
bullet.transform.rotation = Quaternion.Euler(gun.transform.eulerAngles.x, gun.transform.eulerAngles.y, gun.transform.eulerAngles.z);
rb.AddRelativeForce(
bullet.transform.TransformDirection(new Vector2(
(Mathf.Cos(bullet.transform.rotation.z * Mathf.Deg2Rad) * bulletSpeed),
(Mathf.Sin(bullet.transform.rotation.z * Mathf.Deg2Rad) * bulletSpeed))
),
ForceMode2D.Impulse
);
}

CharacterController collision issue

I have added an ability to crouch in the game. The way I've done that is by changing the controller height and center y value. The issue is when I crouch to go underneath a platform the player still collides with the platform even though there's clearly enough space.
If I set the controller height to the crouch height as the default height the player is able to go underneath the platform without trouble. Although, if I use the center offset the collision issue occurs.
bool isCrouching; float defaultHeight; Vector3 localCameraPos;
private CharacterController controller = null;
private Camera camera;
void Start()
{
controller = GetComponent<CharacterController>();
camera = camera.main;
localCameraPos = camera.transform.localPosition;
defaultHeight = controller.height;
}
void Update()
{
isCrouching = Input.GetKey(KeyCode.C);
}
void FixedUpdate()
{
DoCrouch();
}
void DoCrouch()
{
var height = isCrouching ? defaultHeight / 2 : defaultHeight;
controller.height = Mathf.Lerp(controller.height, height, 5 * Time.deltaTime);
controller.center = Vector3.down * (defaultHeight - controller.height) / 2.0f;
var camPos = new Vector3(0, camera.transform.localPosition.y, 0);
camPos.y = Mathf.Lerp(camPos.y, localCameraPos.y - (defaultHeight - controller.height), 5 * Time.deltaTime);
camera.transform.localPosition = camPos + localCameraPos;
}
The player moves by calling CharacterController.move() function.
void FixedUpdate()
{
float horizontal = Input.GetAxis("Horizontal");
float vertical = Input.GetAxis("Vertical");
isWalking = !Input.GetKey(KeyCode.LeftShift);
Vector2 _inputVector = new Vector2(horizontal, vertical);
if (_inputVector.sqrMagnitude > 1) { _inputVector.Normalize(); }
Vector3 desireMoveDir = transform.right * _inputVector.x;
desireMoveDir += transform.forward * _inputVector.y;
if (Physics.SphereCast(transform.position, controller.radius, Vector3.down, out RaycastHit hit, controller.height / 2f, 1))
{
desireMoveDir = Vector3.ProjectOnPlane(desireMoveDir, hit.normal).normalized;
}
moveDirection = desireMoveDir * MoveSpeed;
controller.Move(moveDirection * Time.fixedDeltaTime);
}
How do I fix this issue? Thank you
Well just solved the problem. I had a step offset set to 0.7. Changing it to 0, fixed the problem. Only took me two days...nice

Rotating Rigidbody controller

There is my script Rigidbody controller -
public float Speed = 5f;
public float JumpHeight = 2f;
public float GroundDistance = 0.2f;
public float DashDistance = 5f;
public LayerMask Ground;
private Rigidbody _body;
private Vector3 _inputs = Vector3.zero;
private bool _isGrounded = true;
private Transform _groundChecker;
void Start()
{
_body = GetComponent<Rigidbody>();
_groundChecker = transform.GetChild(0);
}
void Update()
{
_isGrounded = Physics.CheckSphere(_groundChecker.position, GroundDistance, Ground, QueryTriggerInteraction.Ignore);
_inputs = Vector3.zero;
_inputs.x = Input.GetAxis("Horizontal");
_inputs.z = Input.GetAxis("Vertical");
if (_inputs != Vector3.zero)
transform.forward = _inputs;
if (Input.GetButtonDown("Jump") && _isGrounded)
{
_body.AddForce(Vector3.up * Mathf.Sqrt(JumpHeight * -2f * Physics.gravity.y), ForceMode.VelocityChange);
}
if (Input.GetButtonDown("Sprint"))
{
Vector3 dashVelocity = Vector3.Scale(transform.forward, DashDistance * new Vector3((Mathf.Log(1f / (Time.deltaTime * _body.drag + 1)) / -Time.deltaTime), 0, (Mathf.Log(1f / (Time.deltaTime * _body.drag + 1)) / -Time.deltaTime)));
_body.AddForce(dashVelocity, ForceMode.VelocityChange);
}
}
void FixedUpdate()
{
_body.MovePosition(_body.position + _inputs * Speed * Time.fixedDeltaTime);
}
What the best way to make a turn on y in the direction of the camera ? That is,the player turns to the side where the mouse is turned? Is it in fixedUpdate or update?
This is the camera script:
public float Smoothness = 0.3F;
public Vector2 Sensitivity = new Vector2(4, 4);
public Vector2 LimitX = new Vector2(-70, 80);
private Vector2 NewCoord;
public Vector2 CurrentCoord;
private Vector2 vel;
public GameManager GameMangerS;
public Transform Target;
public float TransformSpeed;
public Animator CameraAnimator;
void Update()
{
NewCoord.x = Mathf.Clamp(NewCoord.x, LimitX.x, LimitX.y);
NewCoord.x -= Input.GetAxis("Mouse Y") * Sensitivity.x;
NewCoord.y += Input.GetAxis("Mouse X") * Sensitivity.y;
CurrentCoord.x = Mathf.SmoothDamp(CurrentCoord.x, NewCoord.x, ref vel.x, Smoothness / 2);
CurrentCoord.y = Mathf.SmoothDamp(CurrentCoord.y, NewCoord.y, ref vel.y, Smoothness / 2);
transform.rotation = Quaternion.Euler(CurrentCoord.x, CurrentCoord.y, 0);
}
And added this line to the controller script -
void FixedUpdate()
{
_body.MovePosition(_body.position + _inputs * Speed * Time.fixedDeltaTime);
transform.rotation = Quaternion.Euler(0, MainCamera.CurrentCoord.y, 0);
}
When I'm standing the player normally rotates, but when I start to move, all rotations are reset and the player is not moving.
Update
Simple Rotation can be achieved using transform.Rotate().
Example:
this.transform.Rotate(Vector3.up, 30);
This example is gonna rotate the transform by 30° around the Vector that points upwards.
LookAtMouse:
To make your object turn towards the mouse, you need the ScreenToWorldSpace() method from your camera. In order to convert the ScreenCoordinates into your WorldCoordinates.
Example:
Please note:
You have to set the camera instance! If you don't add that, you'll get a NullReferenceException.
This Snippets shall only show the steps needed to achieve the behavior you wish.
You will have to find out yourself how to integrate that lines of code into your code to make it work. Consider what Programmer told you in the comment when integrating that.
Vector3 mousePosition = Input.mousePosition; //get the screenSpaceMousePosition
Vector3 worldPosition = this.camera.ScreenToWorldPoint(mousePosition); //convert it into worldSpacePosition
Vector3 calculatedDirection = worldPosition - transform.position; //calucate the looking direction
calculatedDirection.y = 0;
Quaternion rotation = Quaternion.LookRotation(calculatedDirection);
transform.rotation = Quaternion.Slerp(transform.rotation, rotation, Time.deltaTime);

How can i rotate a spaceship back to it's original rotation to face the original position?

The spaceship start moving from point A. The spaceship is facing the moving direction.
Now when i click one on the L key i want that the spaceship will rotate and will face to the original position it was start moving from. But even if the spaceship is now rotated by axis Z or Y or X to rotate it first to the regular rotation values and to face to the start moving position.
using UnityEngine;
using System.Collections;
public class Control : MonoBehaviour
{
public int rotationSpeed = 75;
public int movementspeed = 10;
public int thrust = 10;
private bool isPKeyDown = false;
private float acceleration = .0f;
private Vector3 previousPosition = Vector3.zero;
private Rigidbody _rigidbody;
private Vector3 originalPosition;
private Quaternion originalRotation;
// Use this for initialization
void Start()
{
originalPosition = transform.position;
originalRotation = transform.rotation;
_rigidbody = GetComponent<Rigidbody>();
Debug.Log("Acc Speed: " + thrust);
}
// Update is called once per frame
void Update()
{
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("p"))
{
isPKeyDown = Input.GetKey("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);
}
if (Input.GetKey("l"))
{
transform.rotation = Quaternion.Slerp(transform.rotation, originalRotation, 0);
//StartCoroutine(TurnShip(transform, transform., originalRotation.eulerAngles, 1));
//transform.position += transform.forward * Time.deltaTime * movementspeed;
}
}
IEnumerator TurnShip(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;
}
}
void OnGUI()
{
if (isPKeyDown)
{
GUI.Label(new Rect(100, 100, 200, 200), "Acc Speed: " + acceleration);
}
}
}
This is where i click the L button but i tried some things but can't yet find how to do it.
The main goal is if i click once on L the spaceship should automatic rotate if needed and move back to the original position and then land on ground. L stand for landing that's the main goal.
Add a variable on top -
...
private Vector3 originalPosition;
private Quaternion originalRotation;
private bool landShip = false;
...
And use following code in update function -
if (Input.GetKey("l"))
{
landShip = true;
//StartCoroutine(TurnShip(transform, transform., originalRotation.eulerAngles, 1));
//transform.position += transform.forward * Time.deltaTime * movementspeed;
}
if(landShip){
transform.rotation = Quaternion.Slerp(transform.rotation, originalRotation, 0.5f);
}
Once the spaceship lands, set the landShip value back to false.

Categories