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();
}
}
Related
I would like MyCharacter.cs script to move my 3D character forward, backwards, left, and right. I am using Rewired, an advanced input system for Unity.
It works, but rather moving my character forward and backwards, it moves them up and down. I'm still understanding how to access the y, x, and z axis in relation to the code. I thought that:
moveVector.x = player.GetAxis("Horizontal"); // get input by name or action id
moveVector.y = player.GetAxis("Vertical");
Would allow me to go forward and backwards, not up and down.
Here is the code:
// MyCharacter.cs - how to get input from Rewired.Player
using UnityEngine;
using System.Collections;
using Rewired;
//using AC;
[RequireComponent(typeof(CharacterController))]
public class PlayerController : MonoBehaviour
{
public Rigidbody rb;
// The Rewired player id of this character
public int playerId = 0;
// The movement speed of this character
public float moveSpeed = 3.0f;
public float jumpForce;
public float impactVelocity;
// The bullet speed
public float bulletSpeed = 15.0f;
// Assign a prefab to this in the inspector.
// The prefab must have a Rigidbody componet on it in order to work.
public GameObject bulletPrefab;
private Player player; // The Rewired Player
private CharacterController cc;
private Vector3 moveVector;
private bool fire;
private void Awake()
{
//Get the Rewired Player object for this player and keep it for the duration of the character's lifetime
player = ReInput.players.GetPlayer(playerId);
// Get the character controller
cc = GetComponent<CharacterController>();
}
void Update()
{
GetInput();
ProcessInput();
}
private void GetInput()
{
// Get the input from the Rewired Player. All controllers that the Player owns will contribute, so it doesn't matter
// whetther the input is coming from a joystick, the keyboard, mouse, or a custom controller.
moveVector.x = player.GetAxis("Horizontal"); // get input by name or action id
moveVector.y = player.GetAxis("Vertical");
fire = player.GetButtonDown("Fire");
}
private void ProcessInput()
{
// Process movement
if(moveVector.x != 0.0f || moveVector.y != 0.0f)
{
cc.Move(moveVector * moveSpeed * Time.deltaTime);
}
// Process fire
if (fire)
{
GameObject bullet = (GameObject)Instantiate(bulletPrefab, transform.position + transform.right, transform.rotation);
bullet.GetComponent<Rigidbody>().AddForce(transform.right * bulletSpeed, ForceMode.VelocityChange);
}
// Process jump
if(player.GetButtonDown("Jump"))
{
rb.AddForce(Vector3.up * jumpForce);
}
}
}
Use Z coordinate instead Y
moveVector.x = player.GetAxis("Horizontal");
moveVector.z = player.GetAxis("Vertical"); // here
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
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);
}
}
I'm replicating project from this site below:
http://blog.lessmilk.com/unity-spaceshooter-1/
http://blog.lessmilk.com/unity-spaceshooter-2/
But, my bullet does not move forward when the spacebar is pressed. Below are my scripts:
spaceshipScript:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class spaceshipScript : MonoBehaviour {
public GameObject bullet;
// Use this for initialization
void Start () {
}
void Update() {
// Get the rigidbody component
//var r2d = GetComponent("Rigidbody2D");
float speed = 10.0f;
// Move the spaceship when an arrow key is pressed
if (Input.GetKey (KeyCode.RightArrow))
transform.position += Vector3.right * speed * Time.deltaTime;
else if (Input.GetKey (KeyCode.LeftArrow))
transform.position += Vector3.left * speed * Time.deltaTime;
//BULLET
//When spacebar is pressed
if (Input.GetKeyDown(KeyCode.Space)) {
Instantiate(bullet, transform.position, Quaternion.identity);
}
}
}
bulletScript:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class bulletScript : MonoBehaviour {
public int speed = 8;
// Use this for initialization
void Start () {
Input.GetKey (KeyCode.UpArrow);
transform.position += Vector3.right * speed * Time.deltaTime;
}
void OnBecomeInvisible() {
Destroy (gameObject);
}
// Update is called once per frame
void Update () {
}
}
As they are telling you in the comments, you are mixing two different approaches. If you want to modify the position of the bullet using Time.deltaTime you need to move that line to Update()
However if you want to follow the approach of the tutorial, but instead of shooting the bullet from bottom to top, you want to shoot from left to right, you should just change the axis (And dont forget to add a rigid body to the bullet)
// Public variable
public var speed : int = 6;
// Function called once when the bullet is created
function Start () {
// Get the rigidbody component
var r2d = GetComponent("Rigidbody2D");
// Make the bullet move upward
r2d.velocity.x = speed;
}
// Function called when the object goes out of the screen
function OnBecameInvisible() {
// Destroy the bullet
Destroy(gameObject);
}
I want to instantiate a projectile and be able to rotate it as a child of a parent player object.
My player has a 2DRigidbody and box collider 2D, my projectiles also have a 2DRigidbody and box collider 2D, so when I shoot them from the player they bounce the player everywhere, but when I try to instantiate them elsewhere the player either jumps to that location or they appear away from the player, so I'd like to instantiate them as a child of the player.
My code for the Player
using UnityEngine;
using System.Collections;
public class Player : MonoBehaviour {
// Calls Variables
public Rigidbody2D lazer;
public float speed = 1.0f;
public float hitpoints = 100;
public float lazerlevel = 1;
Transform ParentPlayer;
// Initalizes variables
void Start () {
}
// Updates once per frame
void Update () {
var move = new Vector3(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical"), 0);
transform.position += move * speed * Time.deltaTime;
if (Input.GetButtonUp("Fire1")) {
//Rigidbody2D instance = Instantiate(lazer, transform.position = new Vector3(0,-5,0), transform.rotation) as Rigidbody2D;
//Vector3 fwd = transform.TransformDirection(Vector3.down);
//instance.AddForce(fwd * 20 * lazerlevel);
GameObject objnewObject = (GameObject)Instantiate(lazer, new Vector3(0, 0, 0), transform.rotation);
objnewObject.transform.parent = ParentPlayer;
}
}
}
And my code for the lazer
using UnityEngine;
using System.Collections;
public class PlayerProjectileDoom : MonoBehaviour {
void ontriggerenter() {
Destroy(gameObject);
}
void Update () {
Destroy(gameObject, 2F);
}
}
You never assigned ParentPlayer in Player script. And you want to assign instantiated object as the child of Player. So the possible way to achieve this is to instantiate your object first, set it as child and then set the transformations to identity because after setting it as child its transformations will become relative to parent.
For example,
void Update () {
var move = new Vector3(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical"), 0);
transform.position += move * speed * Time.deltaTime;
if (Input.GetButtonUp("Fire1")) {
GameObject objnewObject = Instantiate(lazer) as GameObject;
objnewObject.transform.parent = transform;
objnewObject.transform.localRotation = Quaternion.identity;
objnewObject.transform.localPosition = Vector3.zero;
}
}
Second thing is in your PlayerProjectileDoom script. You did implement OnTriggerEnter in wrong way. You should be careful when you are implementing these messages.
Third thing is you are calling Destroy in Update method, however it will work if you put it in Start. I'd recommend use Update at least as possible and absolutely not for these kind of events.
It should be like,
using UnityEngine;
using System.Collections;
public class PlayerProjectileDoom : MonoBehaviour {
void Start(){
Destroy(gameObject, 2F);
}
// For 3D colliders
void OnTriggerEnter(Collider coll) {
Destroy(gameObject);
}
// For 2D colliders
void OnTriggerEnter2D(Collider2D coll) {
Destroy(gameObject);
}
void Update () {
}
}
So you are using 2D colliders so you should go with 2D collider message and remove the 3D one.
An extra note: OnTriggerEnter or OnTriggerEnter2D will execute only iff you set colliders as Trigger. You can see this Trigger check in Inspector by selecting that gameobject having any collider. But if it is not set to Trigger then you should use OnCollisionEnter2D(Collision2D coll)