- Home /
My enemy wants to shoot me, but he's got a gut full of lead
I swear to you, I hate asking these questions. And I swear that I've been at Google / Youtube all night trying to figure this whole fiasco out. My enemy needs to shoot at me. In fact, following the tutorials here and here I've managed to make some progress. Here's the problem: the projectile forms (clones) but never actually moves. It literally just sits and continually clones without going anywhere. (invisible due to its location in the center of the enemy.) Further, I get the exception evidenced at the bottom of this picture: The way I figure, that's Unity telling me that a projectile doesn't exist, which made sense earlier when I was stumbling along, but now to my untrained eye I have the projectile set. (and like I said, it's cloning, just not going anywhere.) Oh, oops. How silly of me. Here's the Script I'm using:
using UnityEngine;
using System.Collections;
public class Bansheeshot : MonoBehaviour
{
public GameObject projectile = null;
public float timeBetweenShotsMin = 1.5f;
public float timeBetweenShotsMax = 5.0f;
private float _nextShot = 0f;
private Transform _transform;
void Start()
{
_transform = transform;
}
// Update is called once per frame
void Update ()
{
if(Time.time > _nextShot)
{
//Assign new next shot
_nextShot = Time.time + Random.Range(timeBetweenShotsMin, timeBetweenShotsMax);
//Fire the projectile
Instantiate(projectile, _transform.position, _transform.rotation);
}
}
}
I have no idea what in the world I'm doing wrong here. Any and all help or points in the right direction are well appreciated. God bless.
Try removing the line where you assign null to the projectile, that may be causing the null reference error. Also are you sure the prefabs have the scripts attached? When you're in game mode, check if the prefab clone objects have the script attached.
(I removed the question's tag js
and replaced it with c#
, because this is clearly not JavaScript)
Does the projectile appear? Or do you just want to make it move?
Also does the projectile have another script that is responsible for it's movement? The current script alone only instantiates the projectile at a certain spot, which is _transform.position, it doesn'tactually move the projectile. If you have that other script, make sure it's attached onto the projectile prefab
Crap. Sorry about that Lu$$anonymous$$otar, you are absolutely right. So used to asking js questions that I think I just did that by habit.
The projectile only "appears" in the scene and hierarchy windows. You can't actually see it in the scene, but you see the clone instances in hierarchy. Clicking on one and dragging it reveals the projectile to be in the center of the enemy.
@DragonBorn007. You're probably onto something. Went over the tutorial several times, and nothing was mentioned / didn't see anything, but that would make sense...
EDIT: Would this be it?
using UnityEngine;
using System.Collections;
public class Projectile : $$anonymous$$onoBehaviour
{
public float speed = -5.0f;
private Transform _transform;
void Start()
{
_transform = transform;
}
// Update is called once per frame
void Update ()
{
_transform.Translate(new Vector3(0.0f, speed*Time.deltaTime, 0.0f));
if(_transform.position.y > 6f || _transform.position.y < -6f)
{
Destroy(gameObject); //Destroy itself
}
}
}
I'm not entirely sure if changing the _transform variable will actually change the object's transform, because you may be changing the "copy" of the transform and not the reference itself. Try replacing all _transform with just 'transform' like this:
transform.Translate(new Vector3(0.0f, speed*Time.deltaTime, 0.0f));
Let me know if _transform works too
EDIT:
Just tested it out, and both should work.
Answer by Lazy08 · Sep 11, 2013 at 07:09 PM
In the Banshee Shot Code, you're naming a variable "transform" which is just asking for trouble. You don't really need the variable at all, so try it like this:
public class Bansheeshot : MonoBehaviour
{
public GameObject Projectile;
public float timeBetweenShotsMin = 1.5f;
public float timeBetweenShotsMax = 5.0f;
private float nextShot = 0f;
void Update ()
{
if (Time.time > nextShot) {
//Assign new next shot
nextShot = Time.time + Random.Range (timeBetweenShotsMin, timeBetweenShotsMax);
//Fire the projectile
Instantiate (Projectile, transform.position, transform.rotation);
}
}
}
Also, the line Instantiate (Projectile, transform.position, transform.rotation); will create the bullet INSIDE the banshee, and if you haven't set the physics to ignore this collision, it might cause some problems. Place the banshee and it's bullet in different layers and make sure that the layers are set to not collide with each other.
hi Lazy,
Thanks for taking the time to do that. When I inserted your version of the code I got this error: "Assets/Standard Assets/Scripts/Bansheeshot.cs(1,32): error CS0246: The type or namespace name `$$anonymous$$onoBehaviour' could not be found. Are you missing a using directive or an assembly reference?"
I'm assu$$anonymous$$g this is still in C#?
Don't forget the using directives
using UnityEngine;
using System.Collections;
yep, put those in seconds after posting, lol. No dice so far, but have to go get the kids from school so hopefully the fresh air helps. The physics / collisions issue sounds promising. Any advice on how to do that? If not (since it seems like one of those "Google it, it's the basics, man, kind of things) I totally understand.
I dont have much experience with the layers, but You can always adjust where exactly the bullet is firing from so it doesn't collide with the Banshee. For example, if the Banshee if facing in the positive z direction you can try:
Instantiate (Projectile, Vector3(transform.position.x, transform.position.y, transform.position.z + 10), transform.rotation);
That will have the bullet spawn 10 units away from the transform.position.z of the banshee. Just play around with the int values until you get something that looks right. I.e try using 5 ins$$anonymous$$d of 10 or -5 etc..
ok, going through one post at a time. I put the player on a "player" layer, and the projectile on a "projectile" layer, while the Banshee has remained on the default layer. How do I go about ignoring the collision between projectile and default?
EDIT: I found the following here.
Casting Rays Selectively
Using layers you can cast rays and ignore colliders in specific layers. For example you might want to cast a ray only against the player layer and ignore all other colliders.
The Physics.Raycast function takes a bitmask, where each bit deter$$anonymous$$es if a layer will be ignored or not. If all bits in the layer$$anonymous$$ask are on, we will collide against all colliders. If the layer$$anonymous$$ask = 0, we will never find any collisions with the ray.
// JavaScript example.
// bit shift the index of the layer to get a bit mask
var layer$$anonymous$$ask = 1 << 8;
// Does the ray intersect any objects which are in the player layer.
if (Physics.Raycast (transform.position, Vector3.forward, $$anonymous$$athf.Infinity, layer$$anonymous$$ask))
print ("The ray hit the player");
// C# example.
int layer$$anonymous$$ask = 1 << 8;
// Does the ray intersect any objects which are in the player layer.
if (Physics.Raycast(transform.position, Vector3.forward, $$anonymous$$athf.Infinity, layer$$anonymous$$ask))
Debug.Log("The ray hit the player");
Ok, this is still Greek to me though. The projectile layer is 8, and the player layer is 9. The question becomes (assu$$anonymous$$g this is the script I want use (in js or c#) where does it go? (the projectile? The player? Both?) And how do I configure it to ignore said layer(s)?
EDIT 2: Oh for crying out loud. So when the enemy goes flying around the room it leaves behind the projectiles, just floating in midair like little turds. This thing is mocking me now.