I have Enemy prefab that has navmesh agent. The enemy is controlled by the down give script , how can i have random navmesh agent speed using the give script
Enemy Movement
public class EnemyMovement : MonoBehaviour
{
Transform player; // Reference to the player's position.
PlayerHealth playerHealth; // Reference to the player's health.
EnemyHealth enemyHealth; // Reference to this enemy's health.
UnityEngine.AI.NavMeshAgent nav;
void Awake ()
{
player = GameObject.FindGameObjectWithTag ("Player").transform;
playerHealth = player.GetComponent<PlayerHealth>();
enemyHealth = GetComponent <EnemyHealth> ();
nav = GetComponent <UnityEngine.AI.NavMeshAgent> ();
}
void Update ()
{
// If the enemy and the player have health left...
if(enemyHealth.currentHealth > 0 && playerHealth.currentHealth > 0)
{
// ... set the destination of the nav mesh agent to the player.
nav.SetDestination (player.position);
}
// Otherwise...
else
{
// ... disable the nav mesh agent.
nav.enabled = false;
}
}
}
Get random number with UnityEngine.Random.Range(yourMinf, yourMax5f);.
Assign that number to NavMeshAgent.speed.
For example, the snippet below will assign random speed between 2 and 5.
nav.speed = UnityEngine.Random.Range(2f, 5f);
Just put that inside your if statement. You may also be interested in other variables such as NavMeshAgent.angularSpeed and NavMeshAgent.acceleration
Related
I'm writing a script in C# in Unity that essentially functions as a switch to turn gravity on or off for a 2D Rigidbody. When the game starts, gravity should be 0 for the Rigidbody. Then when the user taps the space bar, gravity is supposed to increase to 3 (which is does). Then, however, when the player collides with a gameObject labeled 'InvisGoal', the player should teleport to another location and then gravity should be 0 again. However, the player always falls after coming in contact with InvisGoal and teleporting and I can't figure out why. This is my first project in C# so sorry for any obvious errors.. The script is here:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BallLaunch : MonoBehaviour {
private Rigidbody2D myRigidBody;
public GameObject Ball;
// Use this for initialization
void Start ()
{
myRigidBody = GetComponent<Rigidbody2D> ();
GetComponent<Rigidbody2D>().gravityScale = 0f;
}
// Update is called once per frame
void Update ()
{
if (Input.GetButtonDown ("Jump"))
{
GetComponent<Rigidbody2D> ().gravityScale = 3f;
}
}
void OnTriggerEnter2D(Collider2D other){
if (other.tag == "InvisGoal")
{
Ball.gameObject.GetComponent<Rigidbody2D>().gravityScale = 0f;
transform.position = new Vector3 (0.61f, 1.18f, 0f);
return;
}
}
}
Ball.gameObject.GetComponent<Rigidbody2D>().gravityScale = 0f;
This is likely what is causing the problem.
It sounds like the RigidBody2D you are referencing to in this line is not the same as the one you retrieved beforehand with GetComponent().
GetComponent returns the component of the GameObject you call it from. Therefore in the code I mentioned above,
Ball.gameObject.GetComponent<RigidBody2D>()
and
GetComponent<RigidBody2D>()
would give you an two different RigidBody2D component if the field Ball does not refer to the same GameObject your BallLaunch script is attached to.
[
Supposing BallLaunch script is attached to the Ball you want to set the gravity of (As picture above)
Simply change:
Ball.gameObject.GetComponent<Rigidbody2D>().gravityScale = 0f;
To
GetComponent<Rigidbody2D>().gravityScale = 0f;
Also, since you already referenced your RigidBody2D in your Start method to the field myRigidBody, you can replace all subsequent GetComponent with myRigidBody.
GetComponent<Rigidbody2D>().gravityScale = 0f;
To
myRigidBody.gravityScale = 0f;
I'm working on a 2D game. If I wanted a simple enemy canon shooting side to side every 5 seconds, how would I go about it ?
I know that I would need to add a colider and rigidbody but not quite sure how to approach this, since am still grasping the whole idea
Red = Enemy/ Rough idea/Sketch
Thank you
What you want is to create a type of gameobject to be used as a 'bullet'. This gameobject when spawned has a script on it to make it travel in a certain direction.
You can move them using force (physics) or you can translate them from one place to another which is to move them 'absolutely' and ignore physics in the environment.
Then you can use a collider on this object to detect when it hits the player using either the OnCollisionEnter method or the OnTriggerEnter method.
There are some tutorials on it here so I hope they help.
Creating Shooting
First you need to think how your enemy should behavior, Just walk side by side or find the enemy as Navmesh.
I found this scritpt on unity website:
using UnityEngine;
using System.Collections;
public class EnemyAttack : MonoBehaviour
{
public float timeBetweenAttacks = 0.5f; // The time in seconds between each attack.
public int attackDamage = 10; // The amount of health taken away per attack.
Animator anim; // Reference to the animator component.
GameObject player; // Reference to the player GameObject.
PlayerHealth playerHealth; // Reference to the player's health.
EnemyHealth enemyHealth; // Reference to this enemy's health.
bool playerInRange; // Whether player is within the trigger collider and can be attacked.
float timer; // Timer for counting up to the next attack.
void Awake ()
{
player = GameObject.FindGameObjectWithTag ("Player");
playerHealth = player.GetComponent <PlayerHealth> ();
enemyHealth = GetComponent<EnemyHealth>();
anim = GetComponent <Animator> ();
}
//OntriggerEnter and On triggerExit the enemy will follow enemy everytime the player enter on collide and stop if player exit
void OnTriggerEnter (Collider other)
{
// If the entering collider is the player...
if(other.gameObject == player)
{
// ... the player is in range.
playerInRange = true;
}
}
void OnTriggerExit (Collider other)
{
// If the exiting collider is the player...
if(other.gameObject == player)
{
// ... the player is no longer in range.
playerInRange = false;
}
}
void Update ()
{
// Add the time since Update was last called to the timer.
timer += Time.deltaTime;
// If the timer exceeds the time between attacks, the player is in range and this enemy is alive...
if(timer >= timeBetweenAttacks && playerInRange && enemyHealth.currentHealth > 0)
{
// ... attack.
Attack ();
}
// If the player has zero or less health...
if(playerHealth.currentHealth <= 0)
{
// ... tell the animator the player is dead.
anim.SetTrigger ("PlayerDead");
}
}
void Attack ()
{
// Reset the timer.
timer = 0f;
// If the player has health to lose...
if(playerHealth.currentHealth > 0)
{
// ... damage the player.
playerHealth.TakeDamage (attackDamage);
}
}
}
First have a look at my code
using UnityEngine;
using System.Collections;
public class Layer : MonoBehaviour {
public float health=150f;
void OnCollisionEnter2D(Collision2D beam){
if (beam.gameObject.tag == "Box") {
Destroy (gameObject);
}
Projectile enemyship = beam.gameObject.GetComponent<Projectile> (); // Retrieving enemyship
if (enemyship) {
Destroy (gameObject);
health = health - 100f; // its value is decreasing only once
Debug.Log (health);
if (health < 0f || health == 0f) {
Destroy (enemyship.gameObject); // this line not executing
}
}
}
}
In my above code the value of health is decreasing only once but OnCollisionEnter2D is working properly. That means on first collision the health value decreases by 100f and it becomes 50f but when it collides second time it's value is still 50f. And I have been looking since 3 hour for this solution. Please help me
I am adding little more thing. I am firing a projectile(laser) when I pressed space. So when laser hits twice object was supposed to be destroyed
Okay so first thing you're doing wrong is that your collision logic makes no sense at all. Your colliding object is "let's say a mortal object" which has to "die" whenever it's health is lower or equal to 0 but you're destroying it every time it collides with anything that has tag Box or has component of type Projectile.
To fix this first reduce the health based on these condition and then check if you want to destroy that object or not.
example code:
public float health = 150f;
void OnCollisionEnter2D(Collision2D beam)
{
float damage = 0f; // current damage...
if (beam.gameObject.tag == "Box")
{
// Destroy (gameObject); // do not destroy, just remove health
damage = health; // reduce health to 0
}
else
{
Projectile enemyship = beam.gameObject.GetComponent<Projectile> ();
if (enemyship)
{
// Destroy (gameObject); // again do not destroy.. just reduce health
damage = 100f;
}
}
health -= damage;
Debug.Log (health); // print your health
// check if dead
if (health < 0f || health == 0f) {
Destroy (gameObject); // this line not executing
}
}
I'm making a Shooting game for VR in Unity and I'm unable to shoot the object. Everytime I point the object, it throws this error. I tried other posts with same error but they does not answer my problem.
ERROR-
ArgumentException: The Object you want to instantiate is null.
UnityEngine.Object.CheckNullArgument (System.Object arg, System.String message) (at /Users/builduser/buildslave/unity/build/Runtime/Export/UnityEngineObject.cs:239)
UnityEngine.Object.Instantiate (UnityEngine.Object original) (at /Users/builduser/buildslave/unity/build/Runtime/Export/UnityEngineObject.cs:176)
playerScript+c__Iterator0.MoveNext () (at Assets/Scripts/playerScript.cs:30)
UnityEngine.SetupCoroutine.InvokeMoveNext (IEnumerator enumerator, IntPtr returnValueAddress) (at /Users/builduser/buildslave/unity/build/Runtime/Export/Coroutines.cs:17)
UnityEngine.MonoBehaviour:StartCoroutine(String)
playerScript:Update() (at Assets/Scripts/playerScript.cs:61)
I'm attaching an image for better understanding of the scene. The yellow cubes are the Shooting Object.
Here's the code I'm using-
using UnityEngine;
using System.Collections;
public class playerScript : MonoBehaviour {
//declare GameObjects and create isShooting boolean.
private GameObject gun;
private GameObject spawnPoint;
private bool isShooting;
// Use this for initialization
void Start () {
//only needed for IOS
Application.targetFrameRate = 60;
//create references to gun and bullet spawnPoint objects
gun = gameObject.transform.GetChild (0).gameObject;
spawnPoint = gun.transform.GetChild (0).gameObject;
//set isShooting bool to default of false
isShooting = false;
}
//Shoot function is IEnumerator so we can delay for seconds
IEnumerator Shoot() {
//set is shooting to true so we can't shoot continuosly
isShooting = true;
//instantiate the bullet
GameObject bullet = Instantiate(Resources.Load("bullet", typeof(GameObject))) as GameObject;
//Get the bullet's rigid body component and set its position and rotation equal to that of the spawnPoint
Rigidbody rb = bullet.GetComponent<Rigidbody>();
bullet.transform.rotation = spawnPoint.transform.rotation;
bullet.transform.position = spawnPoint.transform.position;
//add force to the bullet in the direction of the spawnPoint's forward vector
rb.AddForce(spawnPoint.transform.forward * 500f);
//play the gun shot sound and gun animation
GetComponent<AudioSource>().Play ();
gun.GetComponent<Animation>().Play ();
//destroy the bullet after 1 second
Destroy (bullet, 1);
//wait for 1 second and set isShooting to false so we can shoot again
yield return new WaitForSeconds (1f);
isShooting = false;
}
// Update is called once per frame
void Update () {
//declare a new RayCastHit
RaycastHit hit;
//draw the ray for debuging purposes (will only show up in scene view)
Debug.DrawRay(spawnPoint.transform.position, spawnPoint.transform.forward, Color.green);
//cast a ray from the spawnpoint in the direction of its forward vector
if (Physics.Raycast(spawnPoint.transform.position, spawnPoint.transform.forward, out hit, 100)){
//if the raycast hits any game object where its name contains "zombie" and we aren't already shooting we will start the shooting coroutine
if (hit.collider.name.Contains("Shooting Object")) {
if (!isShooting) {
StartCoroutine ("Shoot");
}
}
}
}
}
The problem is this line
GameObject bullet = Instantiate(Resources.Load("bullet", typeof(GameObject))) as GameObject;
It can't find the resource "bullet." Make sure you've deployed it into the right folder.
I have a question about making a particle for jumping, like a dust cloud when the player jumps, here is my player script:
public class PlayerMovement : MonoBehaviour {
public float speed = 5f;
public Transform groundCheck;
public LayerMask groundLayer;
bool grounded = false;
Animator anim;
Rigidbody2D rgbd;
void Start () {
anim = GetComponent<Animator> ();
rgbd = GetComponent<Rigidbody2D> ();
}
void Update () {
}
void FixedUpdate (){
grounded = Physics2D.OverlapCircle (groundCheck.position, 0.2f, groundLayer);
float movex = Input.GetAxis ("Horizontal");
rigidbody2D.velocity = new Vector2 (movex * speed, rigidbody2D.velocity.y);
if (movex > 0){
transform.localScale = new Vector2(1,transform.localScale.y);
} else if (movex < 0){
transform.localScale = new Vector2(-1,transform.localScale.y);
}
if (Input.GetKey (KeyCode.UpArrow)){
if (grounded == true){
rgbd.AddForce (new Vector2(0f, 4f),ForceMode2D.Impulse);
} else {
grounded = false;
}
}
anim.SetFloat ("speed", Mathf.Abs (movex));
anim.SetBool ("grounded", grounded);
}
}
I want him to activate the particle system only once while in midair. I've tried a few things but when the player is in the air the particle system never stopped.
What most people do is create a new copy of the particle system on every need and destroy it later.
So what you would need is a brand new particle system. Expand the Emission tab. In there set the Rate to 0 (0 particles per second). Below Rate there should be an empty list called Bursts. Add one burst. Set Time to 0.0 (should be set by default) and number of particles to whatever you need. That will shoot 1 burst of particles whenever the particle system runs. Note that if Looping is ON than the burst will happen on beginning of every loop.
So far so good. Now make a prefab from it (watch a tutorial if you need). Then, in your code declare a Game Object variable that will serve you as a particle system:
public GameObject jumpParticles;
back to Unity, feed your prefab into the Jump Particles slot in inspector. Now it's all ready to be copied and pasted wherever you need it. So create a method for this:
void SpawnJumpParticles(Vector3 pos){
GameObject tmpParticles = (GameObject)Instantiate(jumpParticles, pos, Quaternion.identity); //look up how to use Instantiate, you'll need it a lot
Destroy(tmpParticles, 3f);
}
this code will spawn particles and auto-destory them in 3 seconds. The pos argument in the function is where the particles will get created. All that's left is to call it from your code where you start the jump. I'll leave that to you :)) good luck.