How to Instantiate player bullet on leftside in unity - c#

In my unity 2D game I've instantiate bullet with player direction but bullet bullet instantiate on right side of player i try to bullet instantiate on player left side.this is my player bullet
public Rigidbody2D playerWeapon;
void Start(){
InvokeRepeating ("PlayerWeapon",1.0f,1.0f);
}
void PlayerWeapon()
{
Rigidbody2D bPrefab = Instantiate (playerWeapon, new Vector3 (transform.position.x, transform.position.y, transform.position.z), Quaternion.identity) as Rigidbody2D;
}

Using transform.forward should do it. You can also use an offset to modify the distance the bullet should be spawned from the player's distance. Try the code below:
public Rigidbody2D playerWeapon;
void Start()
{
InvokeRepeating("PlayerWeapon", 1.0f, 1.0f);
}
void PlayerWeapon()
{
float offset = 5;
Vector3 plyrPos = transform.position;
Quaternion plyrRot = transform.rotation;
Vector3 plyrDir = transform.forward;
Vector3 spawnPos = plyrPos + plyrDir * offset;
Rigidbody2D bPrefab = Instantiate(playerWeapon, spawnPos, plyrRot) as Rigidbody2D;
}
EDIT:
You could also do this instead:
void PlayerWeapon()
{
float shootSpeed = 10f;
float offset = 5;
Rigidbody2D bPrefab = Instantiate(playerWeapon, transform.position + (offset * transform.forward), transform.rotation) as Rigidbody2D;
bPrefab.velocity = transform.forward * shootSpeed;
}
If it is still going in the wrong direction, flip the shootSpeed value to -10, try again and also flip offset to -5. This will likely fix your problem.

Related

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
);
}

How to track transform.position in real time?

I'm working on a little 2d game where you control a planet to dodge incoming asteroids. I'm implementing gravity in the following manner:
public class Gravity : MonoBehaviour
{
Rigidbody2D rb;
Vector2 lookDirection;
float lookAngle;
[Header ("Gravity")]
// Distance where gravity works
[Range(0.0f, 1000.0f)]
public float maxGravDist = 150.0f;
// Gravity force
[Range(0.0f, 1000.0f)]
public float maxGravity = 150.0f;
// Your planet
public GameObject planet;
void Start()
{
rb = GetComponent<Rigidbody2D>();
}
void Update()
{
// Distance to the planet
float dist = Vector3.Distance(planet.transform.position, transform.position);
// Gravity
Vector3 v = planet.transform.position - transform.position;
rb.AddForce(v.normalized * (1.0f - dist / maxGravDist) * maxGravity);
// Rotating to the planet
lookDirection = planet.transform.position - transform.position;
lookAngle = Mathf.Atan2(lookDirection.y, lookDirection.x) * Mathf.Rad2Deg;
transform.rotation = Quaternion.Euler(0f, 0f, lookAngle);
}
}
The problem is that the asteroids are attracted to the initial spawn point of the planet (0,0), it doesn't update in real time with the movement of the planet. So if I move the planet to the corner of the screen, the asteroids are still attracted to the centre of it.
Is there a way to solve this?
Thank you very much and excuse any flagrant errors!
There are 2 ways to get to an object with speed:
get the object to the player and in each update just use the planet.transform.position
using look at first to rotate to the plant and then using vector3.forword as the direction of the movement.
The first solution doesn't work for you so you might want to try the second one.
any way, if your lookAt part doesn't work too you can use
Vector3 dir = target.position - transform.position;
float angle = Mathf.Atan2(dir.y,dir.x) * Mathf.Rad2Deg;
transform.rotation = Quaternion.AngleAxis(angle, Vector3.forward);
or
Vector3 targetPos = target.transform.position;
Vector3 targetPosFlattened = new Vector3(targetPos.x, targetPos.y, 0);
transform.LookAt(targetPosFlattened);

How to face character in its movement direction and at the same time keep it aligned to any surface?

I want to move my player character(human) on a curved surface. But at the same time character shall stay perpendicular to the surface normals and it should face in the movement direction and can handle collisions(if there is a wall ahead, shall not be able to go through it).
I tried to make a parent stay over normals and change the child local rotation towards direction of motion of its parent. But it has several limitations as of now.
Here is the code what i was using:
[SerializeField] float raycastLength = 1f;
bool canPlayerMove = true;
public float speed = 2f;
public Vector3 offset; //object's position offset to ground / surface
public Quaternion childDirection;
private void Update()
{
float moveHorizontal = SimpleInput.GetAxis("Horizontal");
float moveVertical = SimpleInput.GetAxis("Vertical");
Ray ray = new Ray(transform.position, -transform.up);
RaycastHit hitInfo;
if (Physics.Raycast(ray, out hitInfo, raycastLength))
{
transform.rotation = Quaternion.LookRotation(Vector3.up, hitInfo.normal);
transform.position = hitInfo.point + offset;
Debug.DrawLine(ray.origin, hitInfo.point, Color.red);
}
if (canPlayerMove)
{
Vector3 movement = new Vector3(moveHorizontal, 0, moveVertical);
if (movement != Vector3.zero)
{
childDirection = Quaternion.Slerp(transform.GetChild(0).localRotation, Quaternion.LookRotation(movement), 0.15F);
transform.GetChild(0).localRotation = childDirection;
}
transform.Translate(movement * speed * Time.deltaTime, Space.Self);
}
}
first to not make your player go thru walls you want to add a collider to your walls and not set it as trigger, you will also need a rigidbody on your player and this will help in the next steps.
Secondly you will need to acces the rigidBody in code using this: (if you Check Use Gravity it will also stay on your terrain that you made)
private Rigidbody rb;
private float speed = 7.5f;
private void Start()
{
//this gets the rigidbody on the gameObject the script is currently on.
rb = this.GetComponent<Rigidbody>();
}
private void Update()
{
float hor = Input.GetAxis("Horizontal");
float vert = Input.GetAxis("Vertical");
//this will move your player frame independent.
rb.MovePosition(this.transform.position + new Vector3(hor, 0, vert) * speed *
Time.deltaTime);
}
Also make sure that you have a rigidBody on your player, else it will throw an error.

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

Camera always behind player in Unity3d

I'm struggling with this for quit some time now. I have GameObject, being a sphere, which is my player on a 3d Terrain. I have a Camera which is always on a fixed distance from the player, follows it where it goes with below script:
public GameObject player;
private Vector3 offset;
// Use this for initialization
void Start () {
offset = transform.position - player.transform.position;
}
void LateUpdate () {
transform.position = player.transform.position + offset;
}
So far so good. However what I actually want is that the camera rotates with the player, so it always looks into the direction where the sphere is moving, but always stays behind the player at the same fixed distance, so that the player is always visible in the camera view.
There are a lot of scripts available, but the problem with the onces I've seen so far is that the camera indeed rotate with the player, but because the player actually is a rolling sphere the camera view is rolling and turning as well.
The best script I found so far is below, but this one has the same problem as the other onces, the camera rolls with the player.
public Transform target;
public float distance = 3.0f;
public float height = 3.0f;
public float damping = 5.0f;
public bool smoothRotation = true;
public bool followBehind = true;
public float rotationDamping = 10.0f;
void Update () {
Vector3 wantedPosition;
if(followBehind)
wantedPosition = target.TransformPoint(0, height, -distance);
else
wantedPosition = target.TransformPoint(0, height, distance);
transform.position = Vector3.Lerp (transform.position, wantedPosition, Time.deltaTime * damping);
if (smoothRotation) {
Quaternion wantedRotation = Quaternion.LookRotation(target.position - transform.position, target.up);
//Quaternion ownRotation = Quaternion.RotateTowards;
transform.rotation = Quaternion.Slerp (transform.rotation, wantedRotation, Time.deltaTime * rotationDamping);
}
else transform.LookAt (target, target.up);
}
Can anyone help me with this please?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraFollow : MonoBehaviour {
public GameObject player;
public float cameraDistance = 10.0f;
// Use this for initialization
void Start () {
}
void LateUpdate ()
{
transform.position = player.transform.position - player.transform.forward * cameraDistance;
transform.LookAt (player.transform.position);
transform.position = new Vector3 (transform.position.x, transform.position.y + 5, transform.position.z);
}
}
My solution (based on #brennon-provencher answer) with smoothness and auto offset:
public class CameraFollow : MonoBehaviour
{
public GameObject target;
public float speed = 5;
Vector3 offset;
void Start()
{
offset = target.transform.position - transform.position;
}
void LateUpdate()
{
// Look
var newRotation = Quaternion.LookRotation(target.transform.position - transform.position);
transform.rotation = Quaternion.Slerp(transform.rotation, newRotation, speed * Time.deltaTime);
// Move
Vector3 newPosition = target.transform.position - target.transform.forward * offset.z - target.transform.up * offset.y;
transform.position = Vector3.Slerp(transform.position, newPosition, Time.deltaTime * speed);
}
}
You need to move your camera position based on sphere movement direction -
public GameObject player;
private Vector3 offset;
float distance;
Vector3 playerPrevPos, playerMoveDir;
// Use this for initialization
void Start () {
offset = transform.position - player.transform.position;
distance = offset.magnitude;
playerPrevPos = player.transform.position;
}
void LateUpdate () {
playerMoveDir = player.transform.position - playerPrevPos;
playerMoveDir.normalize();
transform.position = player.transform.position - playerMoveDir * distance;
transform.LookAt(player.transform.position);
playerPrevPos = player.transform.position;
}
Edit 2: To fix flickering camera, try this -
void LateUpdate () {
playerMoveDir = player.transform.position - playerPrevPos;
if (playerMoveDir != Vector3.zero)
{
playerMoveDir.normalize();
transform.position = player.transform.position - playerMoveDir * distance;
transform.position.y += 5f; // required height
transform.LookAt(player.transform.position);
playerPrevPos = player.transform.position;
}
}

Categories