Hi i am currently working on a turret shooting script. My bullet shoots boet does not go in the enemy's direction. something is wrong or missing and i cant figure out what. I have looked up alot of solutions but cant find recent ones or good ones.
EDIT:
my enemy's are instantiated so there is multiple of them. would that be part of the problem? if not do i need to provide more details? im kina new to the site so pls forgive me if i do stuff wrong.
public GameObject Enemy;
public GameObject Bullet;
public float bulletForce = 100f;
private Vector3 direction;
// Use this for initialization
void Start ()
{
ShootFunctionRepeat();
}
// Update is called once per frame
void Update ()
{
direction = Enemy.transform.position - this.transform.position;
}
void ShootFunctionRepeat()
{
InvokeRepeating("ShootFunction", 0.0f, 1.0f);
}
void ShootFunction(GameObject Bullet)
{
GameObject temp = Instantiate(Bullet, this.transform.position + direction.normalized, Quaternion.identity);
temp.GetComponent<Rigidbody>().AddForce(direction.normalized * bulletForce);
}
Your code won't work. You need to remove the GameObject Bullet paramter from ShootFunction() because the paramter hides this.Bullet. And also Unity3D will print warning message Trying to Invoke method: Shoot.ShootFunction couldn't be called.: you cannot use InvokeRepeating with method parameters.
Now it works:
I used a bullet prefab assigned to public GameObject Bullet. And public GameObject Enemy was also assigned a Cube GameObject from the inspector.
Full project.
But you still need to think about how to recycle and finally destroy the bullets: In your code, you just Instantiate the bullets, but when will they be destroyed?
It's not easy to know what exactly you are trying to do.
But this will at least fix most issues.
You must always normalize your vectors before they can be used as a
direction. A direction is a vector with a magnitude of 1. If you
simply subtract one location from another you don't get a
normalized vector.
I am not sure if your ShootFunction is
allowed to have a parameter. I don't think so. Access you member
(Bullet) directly.
I also removed an offset in your instantiation location. You might need to add it back in. But I believe it is not necessary.
Sample
public GameObject Enemy;
public GameObject Bullet;
public float bulletForce = 100f;
private Vector3 direction;
// Use this for initialization
void Start ()
{
ShootFunctionRepeat();
}
// Update is called once per frame
void Update ()
{
direction = (Enemy.transform.position - this.transform.position).normalized;
}
void ShootFunctionRepeat()
{
InvokeRepeating("ShootFunction", 0.0f, 1.0f);
}
void ShootFunction()
{
GameObject temp = Instantiate(Bullet, this.transform.position, Quaternion.identity);
temp.GetComponent<Rigidbody>().AddForce(direction.normalized * bulletForce);
}
Related
I have a script that moves instantiated game objects depending on their tag. However, the game objects that have been instantiated are not moving.
Instantiation Script:
void Update()
{
tillNextSpawn += Time.deltaTime;
Debug.Log(tillNextSpawn);
if (tillNextSpawn >= 2)
{
UnityEngine.Debug.Log("Instantiating circle");
screenPosition = Camera.main.ScreenToWorldPoint(new Vector3(Random.Range(0, Screen.width), Random.Range(0, Screen.height), Camera.main.farClipPlane / 2));
Instantiate(circle, screenPosition, Quaternion.identity);
tillNextSpawn = 0.0f;
}
}
Enemy controller script(moves the enemies)
void FixedUpdate()
{
/*GameObject[]*/
var objects = GameObject.FindGameObjectsWithTag("Enemy");
var objectCount = objects.Length;
foreach (var obj in objects)
{
// Move the players accordingly
var rb = obj.GetComponent<Rigidbody2D>();
Debug.Log(rb);
Vector2 direction = (player.position - obj.transform.position).normalized;
rb.velocity = direction * moveSpeed;
}
}
You should be able to that, and the issue maybe somewhere else in your project.
I created a sample project that recreates what you're trying to do, trying to be as similar as I could be to the sample code you send, you can find it here:
https://github.com/webocs/unity-so-sample-tags
For what I can see, your console is sending an exception
get_main is not allowed to be called...
What comes to my mind, is that that exception is breaking the entire execution, and that's why nothing is happening.
As a side note, I don't know your project so I don't really know why you're building it this way. Said that, why aren't you creating an Enemy script that's attached to the enemy prefab? If you have many enemies you're going to be finding and iterating through all of them in each update tic. If you create an Enemy script and attach it to the prefab you should be able to handle the movement of the enemy using the transform of the gameObject that the script is attached to. This way each enemy is a standalone entity.
I hope all of this helps!
Edit:
I've edited the repo and added a scene called "IndividualEnemies" that illustrates what I told you in the comments
If you want the enemy to follow the player, try doing the following:
//Attach this script to the enemy
Transform player;
private Rigidbody2D rb;
private Vector2 movement;
public float moveSpeed;
void Awake()
{
player = ScriptNameOnPlayer.instance.gameObject.transform;
}
// Start is called before the first frame update
void Start()
{
rb = this.GetComponent<Rigidbody2D>();
}
void Update()
{
Vector3 direction = player.position - transform.position;
direction.Normalize();
movement = direction;
}
void FixedUpdate()
{
moveCharacter(movement);
}
void moveCharacter(Vector2 direction)
{
rb.MovePosition((Vector2)transform.position + (direction * moveSpeed * Time.deltaTime));
}
//But make sure your player script has this line of code:
public static ScriptNameOnPlayer instance;
Hope this helps !
So my game is sort of like a 3d top down shooter, so I want my gun to shoot wherever the mouse is and it wont go to the mouse unless im shooting down. If you've seen brackyes game called ball wars, im sort of trying to replicate one like that but the projectile is not shooting the right way.
I got my script from blackthornprods ranged combat tutorial (which is for 2d so maybe thats the issue but I dont know how to solve it) :
public float speed;
public float lifeTime;
private void Start()
{
Invoke("DestoryProjectile", lifeTime);
}
private void Update()
{
transform.Translate(transform.up * speed * Time.deltaTime);
}
void DestroyProjectile()
{
Destroy(gameObject);
}
Appreciate anyone to try!
Here is my other script:
Camera mainCam;
public GameObject projectile;
public Transform shotPoint;
private float timeBtwShots;
public float startTimeBtwShots;
void Awake()
{
mainCam = Camera.main;
}
void Update()
{
float objectDepthFromCamera = Vector3.Dot(
transform.position - mainCam.transform.position,
mainCam.transform.forward);
Vector3 cursorWorldPosition = mainCam.ScreenToWorldPoint(Input.mousePosition
+ Vector3.forward * objectDepthFromCamera);
Vector3 localUpNeeded = Vector3.Cross(Vector3.forward,
cursorWorldPosition - transform.position);
transform.rotation = Quaternion.LookRotation(Vector3.forward, localUpNeeded);
if(timeBtwShots <= 0)
{
if (Input.GetMouseButtonDown(0))
{
Instantiate(projectile, shotPoint.position, transform.rotation);
timeBtwShots = startTimeBtwShots;
}
}
else
{
timeBtwShots -= Time.deltaTime;
}
}
Projectile not shooting direction of my weapon. Simple solution -
First instantiate or pool the instance of projectile.
Set rotation of projection from the rotation of weapon & set location to spawn point
Now fire, or whatever strategy you are using
Consider Global rotation, if you need help, tell me, I will edit and give a snippet of code.
This should work. If doesn't post all necessary code, I will give a better solution.
Here is sample github project I created, just for you. I opened Unity nearly after a year. Please check all the versions.
Must check :
firing in facing direction 💋
just instantiate at spawn point
just added some rotation
I think this should give you concept.
Press X for a rantom rotation
Press Space to shoot a projectile :lol:
The white cube shows that it always shoots at a constant direction
There is a problem with my bullet firing logic.
The first time everything works fine, but when I shoot the bullet after respawning it doesn't move. It only works for the first shot.
The bullet is a prefab.
Here is my code:
public Rigidbody2D bulletrb;
private float dirX=1;
public float speed=.001f;
public Transform playerPos;
private Vector3 bulletPos;
public GameObject bulletObj;
void Update () {
bulletPos.x = playerPos.transform.position.x + 2;
bulletPos.y = playerPos.transform.position.y + 1;
if (Input.GetKeyDown("1"))
{
bulletrb.velocity = new Vector2(dirX * speed, bulletrb.velocity.y);
Debug.Log("Shoot!");
}
}
private void OnTriggerEnter2D(Collider2D target)
{
if(target.gameObject.tag=="Zombie")
{
Destroy(bulletObj);
Debug.Log("Hited!");
Instantiate(bulletObj,bulletPos,Quaternion.identity,playerPos);
}
}
When you call Destroy, you are losing your active bullet GameObject, but when you call Instantiate, it is not actually assigned back to your bulletObj reference.
The quick and simple fix is:
bulletObj = Instantiate(bulletObj, bulletPos, Quaternion.identity, playerPos);
There are probably more improvements that could be made, but this is the gist of the issue.
One recommendation I would make is using bulletObj.SetActive(false) and bulletObj.SetActive(true) instead of Destroy and Instantiate
I'll keep this brief and a bit short, but I currently have a particle system that seems to not be rendering even though my collision works.
I have trouble understanding other peoples work so I have not been able to find a solution I can understand.
Here is my code:
public float speed;
public Rigidbody rb;
public int health;
private float knockback;
private float knockup;
public ParticleSystem Eparticle; //*** variable for particle system ***
// Use this for initialization
void Start()
{
rb = GetComponent <Rigidbody>();
knockback = 100f;
knockup = 250f;
}
void OnCollisionEnter(Collision col)
{
if (col.gameObject.name == "enemy")
{
health = health - 20;
rb.AddRelativeForce(Vector3.back * knockback);
rb.AddRelativeForce(Vector3.up * knockup);
Destroy(col.gameObject);
Instantiate(Eparticle);
}
if (col.gameObject.name == "endgoal")
{
SceneManager.LoadScene("level 1");
}
}
What am I doing wrong with my instantiate(Eparticle) line?
Could someone please talk me through a solution?
Thank You :)
You should invoke the Instantiate method at the position where you want the particle prefab to appear.
You could do something like this...
Instantiate(Eparticle,transform.position,transform.rotation);
Actually, you can also create (instantiate) a GameObject at runtime as follows...
GameObject obj= Instantiate(Eparticle,transform.position,transfrom.rotation) as GameObject;
This way, you have some sort of 'control' over the instantiated gameobject.
For instance, you can destroy the object after using it by calling the Destroy() method.
E.g.:
Destroy(obj,2f);//Destroys the created object after 2 seconds.
Of course, this is not a good way to go about it if you are going to be instantiating and destroying a lot of objects. You should read about Object Pooling for this purpose.
I am making a 2D platformer with Unity and I have run into a small problem. I have enemies that shoot bullets at the player. However, the bullets are only shooting in one direction regardless of which direction the enemy is facing.
In my Enemy Script I have this:
Instantiate(bullet, spawnPosition.position, Quaternion.identity);
and in my bullet script I have this
rigidbody2D.velocity = new Vector2(bulletSpeed,0);
Please help if you can.
I understand why this is happening, but I can not figure out a solution. To update my question I want to be able to check the enemies direction so that I can change the bullet speed to positive/negative to match the direction. Since there will be multiple enemies of this type I do not know how to do this.
public class bulletScript : MonoBehaviour {
// Use this for initialization
private float bulletSpeed;
GameObject parent;
private Vector3 theScale;
void Start () {
rigidbody2D.velocity = new Vector2(bulletSpeed,0);
}
// Update is called once per frame
void Update () {
// if(transform.localScale.x < 0) bulletSpeed = -100;
// if(transform.localScale.x > 0) bulletSpeed = 100;
}
public void SetEnemy(GameObject obj)
{
parent = obj;
}
Then in HammerScript.cs
public class HammerScript : MonoBehaviour {
public bulletScript bullet;
public Transform spawnPosition;
void FixedUpdate ()
{
instantiate(bullet, spawnPosition.position, Quaternion.identity);
((bulletScript)bullet).SetEnemy(this);
}
}
2 new errors:
1-Assets/Scripts/Level 2/HammerScript.cs(89,64): error CS1502: The best overloaded method match for bulletScript.SetEnemy(UnityEngine.GameObject)' has some invalid arguments
2-Assets/Scripts/Level 2/HammerScript.cs(89,64): error CS1503: Argument#1' cannot convert HammerScript' expression to typeUnityEngine.GameObject'
the bullets are only shooting in one direction regardless of which direction the enemy is facing.
Well, unless bulletSpeed is positive or negative depending on the enemy's direction, every bullet will have the same speed and direction. In your code, the bullets' velocities do not depend on the enemies' directions at all.
What you could do is keep a reference in the bullet to the enemy that it came from, and then set the velocity according to that enemy's info.
You can do that by having a SetEnemy method that takes an Enemy as a parameter in your Bullet class, and then you can just call ((bulletScript)bullet).SetEnemy(this); immediately after the Instantiate call.
So your HammerScript file should look like this:
public class HammerScript : MonoBehaviour
{
public bulletScript bullet;
public Transform spawnPosition;
void FixedUpdate ()
{
instantiate(bullet, spawnPosition.position, Quaternion.identity);
((bulletScript)bullet).SetEnemy(this);
}
}
Then, in your Bullet class you can have the following:
class bulletScript : MonoBehavior
{
GameObject parent;
public void SetEnemy(GameObject obj)
{
parent = e;
}
// ... whatever else you have, including the method that sets the velocity
}
Then in your bullet script you would set rigidbody2D.velocity to something that has to do with the enemy (which would be this.parent).
Your current implementation only allow the bullet to go into one direction. Let's assume your bulletSpeed is always positive.
If you consider another direction with the angle alpha from that base direction, then you need to create a rotated Vector, which you can do like this:
new Vector2(bulletSpeed * Mathf.Cos(alpha), bulletSpeed * Mathf.Sin(alpha));
Also consider that alpha has to be given as radians, if you truly want to use degrees calculate the radians first:
alpha = (degrees / 180) * 90