I added this script to the enemy ship and tried using it on the player ship but the projectiles still do not shoot and kill the player ship. I trying to get the laser guns on the enemy ship to kill the player ship. But my script is not working. in the inspector in Unity, I needed to add the player ship to public Rigidbody projectile; so I did when trying to add the script to either or the enemy ship or player ship the enemy laser bullets still don't kill the player ship. But the enemy ship and its bullets follow the player ship though so that works. Any insight is welcomed :/
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Projectiles : MonoBehaviour
{
public Transform playerShip;
public float range = 20.0f;
public float enemyGunImpulse = 10.0f;
bool onRange = false;
public Rigidbody projectile;
void Start()
{
float rand = Random.Range(1.0f, 2.0f);
InvokeRepeating("Shoot", 2, rand);
}
void Shoot()
{
if (onRange)
{
Rigidbody enemyGun = (Rigidbody)Instantiate(projectile, transform.position + transform.forward, transform.rotation);
enemyGun.AddForce(transform.forward * enemyGunImpulse, ForceMode.Impulse);
Destroy(enemyGun.gameObject, 2);
}
}
void Update()
{
onRange = Vector3.Distance(transform.position, playerShip.position) < range;
if (onRange)
transform.LookAt(playerShip);
}
}
Related
I have been trying to find a way for the Enemy to shoot at multiple players or Objects and I don't know where to start.
I'm currently using Unity 2017
Here's the bullet script
Much Appreciated
using UnityEngine;
using System.Collections;
public class MultiBulletScript:
MonoBehaviour {
GameObject[] target;
public float speed;
Rigidbody2D bulletRB;
GameObject destroyObject;
Vector3 respawn = new Vector3(-36, 0, 0);
public GameObject blood;
// Use this for initialization void Start () {
bulletRB = GetComponent < Rigidbody2D > ();
target = GameObject.FindGameObjectsWithTag("Player");
Vector2 moveDir = (target.transform.position - transform.position).normalized * speed;
bulletRB.velocity = new Vector2(moveDir.x, moveDir.y);
Destroy(this.gameObject, 2);
}
private void OnTriggerEnter2D(Collider2D other) {
if (other.gameObject.tag == "Player") {
Instantiate(blood, transform.position, Quaternion.identity);
other.gameObject.transform.position = respawn;
}
if (other.CompareTag("Bullet")) {
Destroy(other.gameObject);
Destroy(gameObject);
}
}
}
You can create a List for objects you want to shoot at. Something like this:
public List<Transform> targets = new List<Transform>();
After this, you need to calculate the direction for all of them. Such as this (where gunPosition is where you want to spawn the bullet and shootRotation is the rotation of your bullet when you shoot it):
public void Start()
{
foreach(Transform target in targets)
{
Vector3 shootDirection = (target.position - transform.position).normalized;
GameObject newBullet = Instantiate(bulletPrefab, gunPosition, shootRotation)
newBullet.GetComponent<RigidBody>().velocity = shootDirection * shootSpeed;
}
}
However, this goes into your enemy controller script. Bullets should only have a small amount of code. They only need to detect the TriggerEnter.
But be aware! Too much OnTriggerEnter calculation in the scene can have an impact on your performance (dropping fps).
So I would create one script on each player with an OnTriggerEnter so they detect if a bullet hits them. They can destroy the bullet as well.
public void OnTriggerEnter(Collider other)
{
if(other.tag == "Bullet")
{
//Do blood effect
//Damage player
Destroy(other.transform.root.gameObject);
}
}
It is better, because there always be less player then bullet, so your game is more optimized. Hope I could help!
So I am trying to have my bullet prefab fire in the same direction that my player is facing. Currently if the player faces north that's where the bullet fires, if the player faces south the bullet still fires north shooting straight through the player backwards.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class FireRocket : MonoBehaviour
{
public GameObject rocketPrefab;
// Update is called once per frame
void Update()
{
if (Input.GetMouseButtonDown(0))
{
GameObject rocketObject = Instantiate(rocketPrefab);
rocketObject.transform.position = this.transform.position + transform.forward;
}
}
}
The bullet has a box collider and a rigidbody with the script attached. What else do i need to include so that I can have my bullet fire in the same direction my player is facing?
Rocket Script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Rocket: MonoBehaviour
{
public float speed = 15f;
public float RocketLife = 10f;
private float RocketLifeTimer;
// Start is called before the first frame update
void Start()
{
RocketLifeTimer = RocketLife;
}
// Update is called once per frame
void Update()
{
transform.position += transform.forward * speed * Time.deltaTime;
RocketLife -= Time.deltaTime;
if (RocketLifeTimer <= 0f)
{
Destroy(this.gameObject);
}
}
}
you need to add transform.rotation = player rotation / or camera rotation
For some odd reason, whenever my rigidbody ball is rolling AWAY from me, and I "shoot it" with a rigidbody projectile, the ball changes direction and moves toward me, as opposed to away from me. Physics are working fine otherwise (if the ball is rolling towards the playerobject when shot with the projectile, the impact of the projectile bounces/knocks the ball away in a correct direction/physics way.)
My bounce code is attached, I use it to bounce the ball off walls/etc and it is working perfectly. I suppose its because the ball is always moving towards a wall when it strikes it. I'm stumped though as to why when I shoot the ball as its rolling away from me it changes direction immediately. I've tried different mass, drags, physics materials, gravity - everything I can think of to no avail.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BounceBall : MonoBehaviour
{
private Rigidbody rb;
public float bounceForce = 6f;
Vector3 lastVelocity;
void Start()
{
rb = GetComponent<Rigidbody>();
}
void LateUpdate()
{
lastVelocity = rb.velocity;
}
private void OnCollisionEnter(Collision collision)
{
GameObject hitObject = collision.gameObject;
if (hitObject.tag == "Pusher")
{
float speed = lastVelocity.magnitude;
Vector3 direction = Vector3.Reflect(lastVelocity.normalized, collision.contacts[0].normal);
rb.velocity = direction * Mathf.Max(speed, bounceForce * 3.5f);
}
else if (hitObject.tag == "Untagged")
{
float speed = lastVelocity.magnitude;
Vector3 direction = Vector3.Reflect(lastVelocity.normalized, collision.contacts[0].normal);
rb.velocity = direction * Mathf.Max(speed, bounceForce);
}
}
}
And the projectile code (don't think this has anything to do with it)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Projectile : MonoBehaviour
{
public GameObject projectile;
[SerializeField] float projVel = 50f;
[SerializeField] float projLifeTime = 3.5f;
[SerializeField] float projTimer;
private Rigidbody rb;
void Start()
{
rb = projectile.GetComponent<Rigidbody>();
projTimer = projLifeTime;
//rb.AddForce(0,projVel,0, ForceMode.Impulse);
rb.AddForce(transform.forward * projVel, ForceMode.Impulse);
}
private void Update()
{
projTimer -= Time.deltaTime;
if(projTimer <= 0f)
{
Destroy(gameObject);
}
}
The problem is the method Vector3.Reflect(). If you put in a backwards velocity it will output a forward velocity. The method Vector3.Reflect() is meant for an object bouncing off a surface or ricochets.
What you want to do is use Rigidbody.AddForce()
Here's the documentation: https://docs.unity3d.com/ScriptReference/Rigidbody.AddForce.html
I'm having an issue instantiating Prefabs in Unity.
I'm working on a game where you have enemies moving towards you and you have to kill them. My original enemy game object moved towards the player with little to no problem, but the instantiations of that object wouldn't move.
To make matters more confusing, when I copied the game object and added it to the scene without instantiation, both game objects would move towards the player just fine.
Enemy script:
public class EnemieController : MonoBehaviour
{
[SerializeField]
float moveSpeed = 1;
[SerializeField]
private Rigidbody2D rb;
public Transform player;
public float health = 50;
void Start()
{
rb = GetComponent<Rigidbody2D>();
Debug.Log(player);
}
// Update is called once per frame
void Update()
{
MoveTowardsPlayer();
}
void MoveTowardsPlayer()
{
Vector3 mousepos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
Vector2 direction = (player.position - transform.position).normalized;
rb.velocity = new Vector2(direction.x * moveSpeed, direction.y * (moveSpeed * 1));
}
}
Instantiation Code
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//using System;
[System.Serializable]
public class GameManagement : MonoBehaviour
{
public GameObject circleEnemie;
public Transform player;
[SerializeField]
float moveSpeed = 1;
// Start is called before the first frame update
void Start()
{
//Get random position to spawn ball
Vector3 screenPosition = Camera.main.ScreenToWorldPoint(new Vector3(Random.Range(0, Screen.width), Random.Range(0, Screen.height), Camera.main.farClipPlane / 2));
GameObject enemie = Instantiate(circleEnemie, screenPosition, Quaternion.identity) as GameObject;
enemie.name = "enemiecircle";
enemie.tag = "Enemie";
}
// Update is called once per frame
void Update()
{
}
}
And if wanted, here are the enemies inspector specifications
Inspector Specifications
Sorry about the link, my reputation points are yet to reach 10 so I can't post images directly.
My guess would be that the Player referenced in your enemy prefab is a prefab itself that never moves.
You should make the prefab field itself of type EnemyController. This makes sure you only can reference a prefab here that actually has an EnemyController attached.
Then after Instantiate you can pass in the player reference of the GameManagement script like
public class GameManagement : MonoBehaviour
{
// Give this field the correct type
public EnemyController circleEnemie;
public Transform player;
[SerializeField]
float moveSpeed = 1;
// Start is called before the first frame update
void Start()
{
//Get random position to spawn ball
Vector3 screenPosition = Camera.main.ScreenToWorldPoint(new Vector3(Random.Range(0, Screen.width), Random.Range(0, Screen.height), Camera.main.farClipPlane / 2));
// Instantiate returns the same type as the given prefab
EnemyController enemy = Instantiate(circleEnemie, screenPosition, Quaternion.identity);
enemy.name = "enemiecircle";
enemy.gameObject.tag = "Enemie";
// Now pass in the player reference
enemy.player = player;
}
// NOTE: When not needed better remove Unity message methods
// It would just cause overhead
//void Update()
//{
//}
}
Sidenote: In your EnemyController in MoveTowardsPlayer what do you need this for?
Vector3 mousepos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
Then whenever dealing with Rigidbody do the things in FixedUpdate otherwise it might break the physics and collision detection!
Then also don't use the Transform values but again the Rigidbody
private void FixedUpdate ()
{
MoveTowardsPlayer();
}
private void MoveTowardsPlayer ()
{
var direction = ((Vector2)(player.position - rb.position)). normalized;
rb.velocity = direction * moveSpeed;
}
I'm making a game that is similar to Space Shooter, and I would like to know how to prevent a player from shooting projectiles AFTER the ammo has depleted.
The two scripts below controls my player's movement and actions, and decreases the current projectile count each time the player hits spacebar.
Player script
using UnityEngine;
using System.Collections;
public class Player : MonoBehaviour {
//Movement speed of Player sprite
public float Speed = 20.5f;
//GameObject to store the projectile object
public GameObject Projectile;
// Update is called once per frame
void Update ()
{
//If left arrow key is pressed
if (Input.GetKey (KeyCode.LeftArrow))
//Move the player to the left
transform.Translate (new Vector2 (-Speed * Time.deltaTime, 0f));
//If right arrow key is pressed
if (Input.GetKey (KeyCode.RightArrow))
//Move the player to the right
transform.Translate (new Vector2 (Speed * Time.deltaTime, 0f));
//If the spacebar is pressed
if (Input.GetKeyDown (KeyCode.Space))
{
//Instatiate a new projectile prefab 2 units above the Player sprite
Instantiate (Projectile, transform.position + transform.up * 2, Quaternion.identity);
//Find the game object with the tag "Projectile" and call the DecreaseProjectileCount() function from the ProjectileTracker script
GameObject.FindGameObjectWithTag("Projectile").GetComponent<ProjectileTracker>().DecreaseProjectileCount();
}
}
}
ProjectileTracker script
using UnityEngine;
using System.Collections;
public class ProjectileTracker : MonoBehaviour {
//Variable to store the current projectile count
public GameObject ProjectileRef;
//Set the current projectile count to be 8
int CurrentProjectileCount = 8;
//Function to decrease the current projectile count
public void DecreaseProjectileCount()
{
//Decrease the current projectile count by 1
CurrentProjectileCount--;
//Print out the current projectile count
ProjectileRef.GetComponent<TextMesh> ().text = CurrentProjecileCount.ToString ();
}
}
Any form of help is appreciated!
The way i would personally do it:
ProjectileTracker tracker = GameObject.FindGameObjectWithTag("Projectile").GetComponent<ProjectileTracker>();
//If the spacebar is pressed
if (Input.GetKeyDown (KeyCode.Space) && tracker.ProjectileCount > 0)
{
//Instatiate a new projectile prefab 2 units above the Player sprite
Instantiate (Projectile, transform.position + transform.up * 2, Quaternion.identity);
//Find the game object with the tag "Projectile" and call the DecreaseProjectileCount() function from the ProjectileTracker script
tracker.ProjectileCount--;
}
...
using UnityEngine;
using System.Collections;
public class ProjectileTracker : MonoBehaviour {
//Variable to store the current projectile count
public GameObject ProjectileRef;
//Set the current projectile count to be 8
private int projectileCount = 8;
public int ProjectileCount
{
get { return projectileCount; }
set { SetProjectileCount(value); }
}
//Function to decrease the current projectile count
public void SetProjectileCount(int value)
{
projectileCount = value;
//Print out the current projectile count
ProjectileRef.GetComponent<TextMesh> ().text = value.ToString();
}
}