I can't apply anything to this 'bullet' I instantiate, i can't access the scipts on it. After instatiate, I want the var in scriptbullter attached to it to take the value of 1.
if (Input.GetMouseButton (1) && canFire) {
var mousePosition = FindObjectOfType<Camera> ().ScreenToWorldPoint (new Vector3 (Input.mousePosition.x, Input.mousePosition.y, Input.mousePosition.z - FindObjectOfType<Camera> ().transform.position.z));
GetComponent<Rigidbody2D> ().transform.eulerAngles = new Vector3 (0, 0, Mathf.Atan2 ((mousePosition.y - transform.position.y), (mousePosition.x - transform.position.x)) * Mathf.Rad2Deg - 90);
bullet bulletobj = Instantiate (bulletFired, transform.position + transform.forward * 2, Quaternion.identity) as bullet;
bulletobj.GetComponent<scriptbullet>().bulletDamages = 1; //this line doesn't work
bulletobj.GetComponent<Rigidbody2D> ().velocity = (mousePosition - transform.position).normalized * bulletSpeed * Time.smoothDeltaTime;
canFire = false;
}
Thanks in advance guys :D
The bulletobj.GetComponent<scriptbullet>() is failing because bulletobj is null. The object returned from Instantiate is not a bullet but instead is a GameObject, change that line of code to
GameObject bulletobj = Instantiate (bulletFired, transform.position + transform.forward * 2, Quaternion.identity) as GameObject;
Related
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 make a bullet fly in an arc when shooting and hit the player.
As in this picture . I tried to use formulas from physics, the body is thrown at an angle to the horizon, that's what came of it . But the bullet flies away into the void
velocity = Mathf.Round(Vector3.Distance(lastpos, transform.position) / Time.deltaTime);
lastpos = transform.position;
Vector3 direction = PlayeCar.position - Vector3.zero;
float angle = Mathf.Atan2(direction.y, direction.x); // радианы
float x = velocity * Mathf.Cos(angle) + gravity * (time* time) / 2;
float y = velocity * Mathf.Sin(angle);
transform.position = new Vector2(x, y)
;
Sample orientative method could be (The script would be attached to the gun that shots, so when the code referes to transform, refers to the gun's transfom):
public void LaunchTarget()
{
Vector3 initialSpeed = transform.forward; //shot direction, gun's forward
GameObject go = GameObject.Instantiate(m_bullet);//reference to bullet prefab
//in case you need to randomize the shot speed
initialSpeed = transform.forward * Random.Range(m_minLaunchSpeed, m_maxLaunchSpeed);
//set the initial position of the bullet in the gun
go.transform.position = transform.position;
// shoot (give speed to the bullets rigidbody)
go.GetComponent<Rigidbody>().velocity = initialSpeed;
//initially disabled soas to see the bullet when shot
go.SetActive(true);
}
Hope that helps
I did it !!!! at the time of the bullet’s flight, I turn it toward the player in an intermittent manner. And after a while I delete it
void Start()
{
rigidbodyBullet = GetComponent<Rigidbody2D>();
Player = GameObject.Find("carPlayer").GetComponent<Transform>();
_distance = Vector3.Distance(Player.position, transform.position);
Invoke("DestroyArcBullet", 1.5f);
limitDistance = _distance / 1.3f;
}
void Update()
{
transform.position += transform.up * Time.deltaTime * 5f;
_distance = Vector3.Distance(Player.position, transform.position);
if (_distance < limitDistance)
{
var turn = Quaternion.Lerp(transform.rotation,
Quaternion.LookRotation(Vector3.forward, Player.position - transform.position), Time.deltaTime * 2);
rigidbodyBullet.MoveRotation(turn.eulerAngles.z);
}
if (this.transform.position.y + this.transform.position.y <= -10 || this.transform.position.y + this.transform.position.y >= 10
|| this.transform.position.x + this.transform.position.x <= -10 || this.transform.position.x + this.transform.position.x >= 10)
{
Destroy(gameObject);
}
}
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);
}
}
I searched around for a while but I couldn't figure out how to solve this nasty bug. I am using a top down view (pointing towards -z), basically 2d with 3d objects and camera in perspective mode.
I need to orient an object towards the mouse , ignoring the z aspect, as everything moves on the same plane.
I am using the following code:
Vector3 mouseToWorld = Camera.main.ScreenToWorldPoint(Input.mousePosition + new Vector3(0, 0, 1f));
mouseToWorld.z = 0f;
Vector3 difference = mouseToWorld - transform.position;
difference.Normalize();
float angle = Mathf.Atan2(difference.y, difference.x) * Mathf.Rad2Deg;
transform.rotation = Quaternion.Euler(0f, 0f, angle - 90);
Unfortunately it only works when the object is still, and breaks as soon as the velocity is > 0;
Any hint would be appreciated :)
p.s. I am adding 1 to the z and then resetting it, because otherwise the mouseToWorld is constantly 0 wherever I move the pointer.
Perhaps it breaks because the velocity vector and the mouse direction aren't the same.
the following script will make an arrow follow the mouse, It's basically the same as yours except it updates the position as well:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class FollowMouse : MonoBehaviour {
public float moveSpeed = 0.01f;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
transform.position = Vector2.Lerp(transform.position, Camera.main.ScreenToWorldPoint(Input.mousePosition), moveSpeed);
Vector3 difference = Camera.main.ScreenToWorldPoint(Input.mousePosition) - transform.position;
difference.Normalize();
float rotation_z = Mathf.Atan2(difference.y, difference.x) * Mathf.Rad2Deg;
transform.rotation = Quaternion.Euler(0f, 0f, rotation_z);
}
}
Thanks for the answer! I figured out you need to subtract the distance between the player and the camera to the initial mouse position:
Vector3 mouseToWorld = Camera.main.ScreenToWorldPoint(Input.mousePosition - new Vector3(0, 0, Camera.main.transform.position.z));
Here the working script:
Vector3 mouseToWorld = Camera.main.ScreenToWorldPoint(Input.mousePosition - new Vector3(0, 0, Camera.main.transform.position.z));
//Debug.DrawLine(transform.position, mouseToWorld);
mouseToWorld.z = 0f;
Vector3 difference = mouseToWorld - transform.position;
difference.Normalize();
float angle = Mathf.Atan2(difference.y, difference.x) * Mathf.Rad2Deg;
transform.rotation = Quaternion.Euler(0f, 0f, angle - 90);
Can't get this line to work without error, it needs a temp variable. Without it the camera is flat on the ground
transform.position.y = currentHeight;
error CS1612: Cannot modify a value type return value of `UnityEngine.Transform.position'. Consider storing the value in a temporary variable
Part of the code is not mine, just trying to convert from java script to c-sharp and implement in my current camera script
// Calculate the current rotation angles
var wantedRotationAngle = target.eulerAngles.y;
var wantedHeight = target.position.y + height;
var currentRotationAngle = transform.eulerAngles.y;
var currentHeight = transform.position.y;
// Damp the rotation around the y-axis
currentRotationAngle = Mathf.LerpAngle (currentRotationAngle, wantedRotationAngle, rotationDamping * Time.deltaTime);
// Damp the height
currentHeight = Mathf.Lerp (currentHeight, wantedHeight, heightDamping * Time.deltaTime);
// Convert the angle into a rotation
var currentRotation = Quaternion.Euler (0, currentRotationAngle, 0);
// Set the position of the camera on the x-z plane to:
// distance meters behind the target
transform.position = target.position;
transform.position -= currentRotation * Vector3.forward * distance;
// Set the height of the camera
transform.position.y = currentHeight;
// Always look at the target
transform.LookAt (target);
I do not believe you can set the seperate axis' of the vector like that, one way you'd do it is
// Calculate the current rotation angles
var wantedRotationAngle = target.eulerAngles.y;
var wantedHeight = target.position.y + height;
var currentRotationAngle = transform.eulerAngles.y;
var currentHeight = transform.position.y;
// Damp the rotation around the y-axis
currentRotationAngle = Mathf.LerpAngle (currentRotationAngle, wantedRotationAngle, rotationDamping * Time.deltaTime);
// Damp the height
currentHeight = Mathf.Lerp (currentHeight, wantedHeight, heightDamping * Time.deltaTime);
// Convert the angle into a rotation
var currentRotation = Quaternion.Euler (0, currentRotationAngle, 0);
// Set the position of the camera on the x-z plane to:
// distance meters behind the target
transform.position = target.position;
transform.position -= currentRotation * Vector3.forward * distance;
// Set the height of the camera
Vector3 temp = transform.position; //Get the current vector the transform is at
temp.y = currentHeight; //assign the new value to the Y axis
transform.position = temp; //replace the existing vector with the new one we just modified.
// Always look at the target
transform.LookAt (target);
so we are replacing your transform.position.y = currentHeight; line with
Vector3 temp = transform.position; //Get the current vector the transform is at
temp.y = currentHeight; //assign the new value to the Y axis
transform.position = temp; //replace the existing vector with the new one we just modified.
This is simply due to the way C# is handling structs and properties, to my belief.
You cannot modify transform.position x and y directly, instead of that you should create a Vector3 variable with desired values and then assign your transform.position to it. For example:
Vector3 newPosition = new Vector3(0, currentHeight, 0);
transform.position = newPosition;