Unity 2D health bar - c#

I am new to coding and Unity
I have the health bar appearing on my screen, but I am not sure how to link the Health script of the health bar to my player script and my player's health script. Simply, I want to make it so when my player gets shot my health bar will lose a heart
my health bar script
using UnityEngine;
using System.Collections;
public class Health : MonoBehaviour {
public int startHealth;
public int healthPerHeart;
private int maxHealth;
private int currentHealth;
public Texture[] heartImages;
public GUITexture heartGUI;
private ArrayList hearts = new ArrayList();
// Spacing:
public float maxHeartsOnRow;
private float spacingX;
private float spacingY;
void Start () {
spacingX = heartGUI.pixelInset.width;
spacingY = -heartGUI.pixelInset.height;
AddHearts(startHealth/healthPerHeart);
}
public void AddHearts(int n) {
for (int i = 0; i <n; i ++) {
Transform newHeart = ((GameObject)Instantiate(heartGUI.gameObject,this.transform.position,Quaternion.identity)).transform; // Creates a new heart
newHeart.parent = transform;
int y = (int)(Mathf.FloorToInt(hearts.Count / maxHeartsOnRow));
int x = (int)(hearts.Count - y * maxHeartsOnRow);
newHeart.GetComponent<GUITexture>().pixelInset = new Rect(x * spacingX,y * spacingY,58,58);
newHeart.GetComponent<GUITexture>().texture = heartImages[0];
hearts.Add(newHeart);
}
maxHealth += n * healthPerHeart;
currentHealth = maxHealth;
UpdateHearts();
}
public void modifyHealth(int amount) {
currentHealth += amount;
currentHealth = Mathf.Clamp(currentHealth,0,maxHealth);
UpdateHearts();
}
void UpdateHearts() {
bool restAreEmpty = false;
int i =0;
foreach (Transform heart in hearts) {
if (restAreEmpty) {
heart.guiTexture.texture = heartImages[0]; // heart is empty
}
else {
i += 1; // current iteration
if (currentHealth >= i * healthPerHeart) {
heart.guiTexture.texture = heartImages[heartImages.Length-1]; // health of current heart is full
}
else {
int currentHeartHealth = (int)(healthPerHeart - (healthPerHeart * i - currentHealth));
int healthPerImage = healthPerHeart / heartImages.Length; // how much health is there per image
int imageIndex = currentHeartHealth / healthPerImage;
if (imageIndex == 0 && currentHeartHealth > 0) {
imageIndex = 1;
}
heart.guiTexture.texture = heartImages[imageIndex];
restAreEmpty = true;
}
}
}
}
}
my player script
/// <summary>
/// Player controller and behavior
/// </summary>
public class PlayerScript : MonoBehaviour
{
public Health health;
/// <summary>
/// 1 - The speed of the ship
/// </summary>
public Vector2 speed = new Vector2(50, 50);
// 2 - Store the movement
private Vector2 movement;
void OnCollisionEnter2D(Collision2D collision)
{
bool damagePlayer = false;
// Collision with enemy
EnemyScript enemy = collision.gameObject.GetComponent<EnemyScript>();
if (enemy != null)
{
// Kill the enemy
HealthScript enemyHealth = enemy.GetComponent<HealthScript>();
if (enemyHealth != null) enemyHealth.Damage(enemyHealth.hp);
damagePlayer = true;
}
// Damage the player
if (damagePlayer)
{
HealthScript playerHealth = this.GetComponent<HealthScript>();
if (playerHealth != null) playerHealth.Damage(1);
}
}
void Update()
{
// 3 - Retrieve axis information
float inputX = Input.GetAxis("Horizontal");
float inputY = Input.GetAxis("Vertical");
// 4 - Movement per direction
movement = new Vector2(
speed.x * inputX,
speed.y * inputY);
// 5 - Shooting
bool shoot = Input.GetButtonDown("Fire1");
shoot |= Input.GetButtonDown("Fire2");
// Careful: For Mac users, ctrl + arrow is a bad idea
if (shoot)
{
WeaponScript weapon = GetComponent<WeaponScript>();
if (weapon != null)
{
// false because the player is not an enemy
weapon.Attack(false);
}
}
// 6 - Make sure we are not outside the camera bounds
var dist = (transform.position - Camera.main.transform.position).z;
var leftBorder = Camera.main.ViewportToWorldPoint(
new Vector3(0, 0, dist)
).x;
var rightBorder = Camera.main.ViewportToWorldPoint(
new Vector3(1, 0, dist)
).x;
var topBorder = Camera.main.ViewportToWorldPoint(
new Vector3(0, 0, dist)
).y;
var bottomBorder = Camera.main.ViewportToWorldPoint(
new Vector3(0, 1, dist)
).y;
transform.position = new Vector3(
Mathf.Clamp(transform.position.x, leftBorder, rightBorder),
Mathf.Clamp(transform.position.y, topBorder, bottomBorder),
transform.position.z
);
}
void FixedUpdate()
{
// 5 - Move the game object
rigidbody2D.velocity = movement;
}
void OnDestroy()
{
Application.LoadLevel("gameOver");
}
}
and my player's health script
using UnityEngine;
/// <summary>
/// Handle hitpoints and damages
/// </summary>
public class HealthScript : MonoBehaviour
{
/// <summary>
/// Total hitpoints
/// </summary>
public int hp = 1;
/// <summary>
/// Enemy or player?
/// </summary>
public bool isEnemy = true;
/// <summary>
/// Inflicts damage and check if the object should be destroyed
/// </summary>
/// <param name="damageCount"></param>
public void Damage(int damageCount)
{
hp -= damageCount;
if (hp <= 0)
{
// 'Splosion!
SpecialEffectsHelper.Instance.Explosion(transform.position);
// Dead!
Destroy(gameObject);
}
}
void OnTriggerEnter2D(Collider2D otherCollider)
{
// Is this a shot?
ShotScript shot = otherCollider.gameObject.GetComponent<ShotScript>();
if (shot != null)
{
// Avoid friendly fire
if (shot.isEnemyShot != isEnemy)
{
Damage(shot.damage);
// Destroy the shot
Destroy(shot.gameObject); // Remember to always target the game object, otherwise you will just remove the script
}
}
}
}

With new UI system in Unity 4.6 it is really easy to create a health bar.
GameObject->UI->Image
Put your health bar sprite in image.
Change the Image type to Filled. Then you can play with Fill amount property and also control in through code

In your PlayerScript you retrieve the HealthScript with the following code:
HealthScript playerHealth = this.GetComponent<HealthScript>();
If you want to call methods on the Health script you would do something similar.
Health healthBar = this.GetComponent<Health>();
healthBar.modifyHealth(amountOfDamage);
This assumes all 3 scripts are on the same Game object.

Related

How to simulate car moving 2D via WheelJoint2D.motorSpeed?

Please, help me.
The farther from the center of the screen the higher / lower the car speed. Car's RigidBody2D.mass = 1000, wheels's mass = 50. The car object has 2 'WheelJoint2D' components (connected RigidBody = frontwheel and backwheel) and useMotor = true, maximumMotorForce = 10000 (by default).
Here is part of my code (C#):
[RequireComponent(typeof(Rigidbody2D), typeof(WheelJoint2D))]
public class CarBaseMovement : MonoBehaviour, IVehicleMovable
{
public const float GRAVITY = 9.81f;
[Header("Wheels Joint")]
[SerializeField] protected WheelJoint2D _frontWheelJoint;
[SerializeField] protected WheelJoint2D _backWheelJoint;
private int _centerScreenX;
protected Rigidbody2D _rigidBody2D;
private float _movementInput;
private float _deltaMovement;
private float _physicValue;
private JointMotor2D _wheelMotor;
private void Start()
{
// set center screen width
_centerScreenX = Screen.width / 2;
_rigidBody2D = GetComponent<Rigidbody2D>();
if (_rigidBody2D == null || _frontWheelJoint == null || _backWheelJoint == null)
{
throw new ArgumentNullException();
}
_wheelMotor = _backWheelJoint.motor;
}
protected virtual void Update()
{
// _movementInput = Input.GetAxis("Horizontal");
if (Input.GetMouseButton(0))
{
_deltaMovement = Input.mousePosition.x;
GetTouch(_deltaMovement);
SetVelocity();
SetWheelsMotorSpeed();
}
}
/// <summary>
/// Get touch/mouseclick position to determine speed
/// </summary>
/// <param name="touchPos">touch/mouseclick position</param>
protected void GetTouch(float touchPos)
{
if (touchPos > _centerScreenX)
{
_movementInput = touchPos - _centerScreenX;
}
if (touchPos < _centerScreenX)
{
_movementInput = _centerScreenX - touchPos;
}
}
/// <summary>
/// Set velocity
/// </summary>
private void SetVelocity()
{
_physicValue = GRAVITY * Mathf.Sin((transform.eulerAngles.z * Mathf.PI) / 180f) * 80f;
_wheelMotor.motorSpeed = Mathf.Clamp(
_wheelMotor.motorSpeed - ( _movementInput - _physicValue) * Time.deltaTime,
-7000f,
7000f);
}
/// <summary>
/// Set wheels motor speed
/// </summary>
private void SetWheelsMotorSpeed()
{
_frontWheelJoint.motor = _backWheelJoint.motor = _wheelMotor;
}
}

Unity3D NavMeshAgent

I've been attempting to rid myself of this NavMeshAgent error for about 2 weeks now but can't seem to overcome it so I'm turning to SO.
I have a Navigation Mesh, I have prodigally spawned enemies which are placed on the Navigation Mesh however I receive this error constantly to where my console is filled (999+) with this error. The error is:
"SetDestination" can only be called on an active agent that has been placed on a NavMesh.
UnityEngine.AI.NavMeshAgent:SetDestination(Vector3)
ZombieAI:Update() (at Assets/Scripts/ZombieAI.cs:137)
Any help on squashing this error would be greatly appreciated as it sucks all performance out of my program to a point of not being usable.
The script is as follows:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
using FSG.MeshAnimator;
public class ZombieAI : MonoBehaviour
{
/// <summary>
/// Components
/// </summary>
MeshAnimator mesh;
AudioSource audioSrc;
SphereCollider sphereCollider;
CapsuleCollider capsuleCollider;
NavMeshAgent agent;
/// <summary>
/// Child Objects
/// </summary>
GameObject EnemyIcon;
/// <summary>
/// Animations
/// </summary>
public MeshAnimation[] deathAnimations = new MeshAnimation[5];
string curDeathAnimations;
public MeshAnimation[] runAnimations = new MeshAnimation[1];
/// <summary>
/// Sounds
/// </summary>
public AudioSource _as;
public AudioClip[] infectedNoises;
public int randomNoiseNum;
/// <summary>
/// Textures
/// </summary>
public Texture[] mantexture = new Texture[16];
public Texture[] womantexture = new Texture[17];
/// <summary>
/// Health
/// </summary>
public float max_health = 5f;
public float cur_health = 5f;
public float distance;
/// <summary>
/// Awareness
/// </summary>
public bool female;
public bool alive;
public bool spotted = false;
public bool attack = false;
bool create = false;
/// <summary>
/// Targets
/// </summary>
public GameObject target;
/// <summary>
/// Veriables
/// </summary>
public float velocity;
private Vector3 previous;
[Range(0f, 1.35f)]
public float attackRange;
[Range(3f, 5f)]
public float runAttackRange;
[Range(1f, 100f)]
public float detectionRange;
[Range(1f, 10f)]
public float runSpeed = 3.5f;
float onMeshThreshold = 3;
private void Start()
{
if (female == false)
{
gameObject.GetComponent<Renderer>().material.SetTexture("_MainTex", mantexture[Random.Range(0, mantexture.Length)]);
}
if (female == true)
{
GetComponent<Renderer>().material.SetTexture("_MainTex", womantexture[Random.Range(0, womantexture.Length)]);
}
curDeathAnimations = deathAnimations[Random.Range(0, deathAnimations.Length)].name;
//EnemyIcon = transform.Find("Enemy-Icon").gameObject;
mesh = GetComponent<MeshAnimator>();
audioSrc = GetComponent<AudioSource>();
_as = GetComponent<AudioSource>();
sphereCollider = GetComponent<SphereCollider>();
capsuleCollider = GetComponent<CapsuleCollider>();
agent = GetComponent<NavMeshAgent>();
target = GameObject.FindGameObjectWithTag("Player");
alive = true;
if (transform.position.y <= 0 && transform.position.y >= 1)
{
Destroy(gameObject);
}
}
public void Update()
{
if (alive)
{
distance = Vector3.Distance(target.transform.position, transform.position);
velocity = ((transform.position - previous).magnitude) / Time.deltaTime;
previous = transform.position;
if (transform.position.y <= 1 && transform.position.y >= -1)
{
create = true;
if (create == false)
{
Destroy(gameObject);
}
else if (create == true)
{
agent.SetDestination(target.transform.position);
}
}
if (velocity > 0 && !attack)
{
mesh.speed = velocity / 3;
mesh.Play("Run1-0");
}
if (velocity > 0 && attack && spotted)
{
spotted = true;
mesh.Play("Run Attack");
}
else if (velocity == 0 && attack && spotted)
{
mesh.Play("Attack1-0");
}
if (distance < detectionRange)
{
spotted = true;
}
if (spotted && distance < attackRange)
{
Vector3 targetPosition = new Vector3(target.transform.position.x, transform.position.y, target.transform.position.z);
transform.LookAt(targetPosition);
}
randomNoiseNum = Random.Range(0, 400);
if (alive && randomNoiseNum == 20)
{
PlayRandomNoise();
}
}
/* if (alive && distance > attackRange && velocity <= 0.05f && !attack)
{
mesh.Play("Idle1-0");
}*/
if (!alive)
{
//mesh.Play(curDeathAnimations);
//ScoreManager.scoreValue += 1;
Destroy(gameObject, 5);
}
if (cur_health <= 0)
{
mesh.speed = 1;
alive = !alive;
mesh.Play(curDeathAnimations);
//Destroy(mesh,0);
Destroy(EnemyIcon);
Destroy(audioSrc, 0);
Destroy(sphereCollider, 0);
Destroy(capsuleCollider, 0);
Destroy(agent, 0);
alive = false;
}
}
void OnTriggerStay(Collider col)
{
attack = true;
}
void OnTriggerExit(Collider col)
{
attack = false;
}
public void PlayRandomNoise()
{
if (female == true)
{
_as.volume = 2.0f;
_as.clip = infectedNoises[Random.Range(0, infectedNoises.Length)];
_as.pitch = Random.Range(1.10f, 1.35f);
_as.PlayOneShot(_as.clip);
}
else
{
_as.volume = 2.0f;
_as.pitch = Random.Range(0.75f, 1.05f);
_as.clip = infectedNoises[Random.Range(0, infectedNoises.Length)];
_as.PlayOneShot(_as.clip);
}
}
}

MovingPlatform - move position1 to position2 then wait for 3 sec

I have one PlatformManager (Script Attached)
One is Position-1
One is Position-2
One is MovingPlatform
I want.
MovingPlatform move Position-1 to Position-2 then wait for 5 Sec
then MovingPlatform move Position-2 to Position-1 then wait for 5 Sec
Here is code for PlatformManager & its working fine without Wait
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MovingPlatform : MonoBehaviour
{
public Transform movingPlatform;
public Transform position1;
public Transform position2;
public Vector3 newPosition;
public string currentState;
public float smooth;
public float resetTime;
private void Start()
{
ChangeTarget();
}
private void FixedUpdate()
{
movingPlatform.position = Vector3.Lerp(movingPlatform.position, newPosition, smooth * Time.deltaTime);
}
void ChangeTarget()
{
if (currentState == "Moving To Position 1")
{
currentState = "Moving To Position 2";
newPosition = position2.position;
}
else if (currentState == "Moving To Position 2")
{
currentState = "Moving To Position 1";
newPosition = position1.position;
}
else if (currentState == "")
{
currentState = "Moving To Position 2";
newPosition = position2.position;
}
Invoke("ChangeTarget", resetTime);
}
}
I have tried this code but MovingPlatform didnt Wait
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TestMovingPlatform : MonoBehaviour
{
public Transform movingPlatform;
public Transform position1;
public Transform position2;
public Vector3 newPosition;
public string currentState;
public float smooth;
public float resetTime;
IEnumerator Start()
{
while (true)
{
yield return StartCoroutine(ChangeTarget());
yield return new WaitForSeconds(3.0f);
}
}
private void FixedUpdate()
{
movingPlatform.position = Vector3.Lerp(movingPlatform.position, newPosition, smooth * Time.deltaTime);
}
IEnumerator ChangeTarget()
{
if (currentState == "Moving To Position 1")
{
currentState = "Moving To Position 2";
newPosition = position2.position;
}
else if (currentState == "Moving To Position 2")
{
currentState = "Moving To Position 1";
newPosition = position1.position;
}
else if (currentState == "")
{
currentState = "Moving To Position 2";
newPosition = position2.position;
}
Invoke("ChangeTarget", resetTime);
yield return null;
}
}
Also i tried This but not success
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TestMovingPlatform : MonoBehaviour
{
public Transform movingPlatform;
public Transform position1;
public Transform position2;
public Transform position3;
public Vector3 newPosition;
public string currentState;
public float smooth;
public float resetTime;
IEnumerator Start()
{
while (true)
{
yield return StartCoroutine(ChangeTarget());
}
}
private void FixedUpdate()
{
movingPlatform.position = Vector3.Lerp(movingPlatform.position, newPosition, smooth * Time.deltaTime);
}
IEnumerator ChangeTarget()
{
if (currentState == "Moving To Position 1")
{
currentState = "Moving To Position 2";
newPosition = position2.position;
yield return new WaitForSeconds(3);
}
else if (currentState == "Moving To Position 2")
{
currentState = "Moving To Position 1";
newPosition = position1.position;
yield return new WaitForSeconds(3);
}
else if (currentState == "")
{
currentState = "Moving To Position 2";
newPosition = position2.position;
yield return new WaitForSeconds(3);
}
Invoke("ChangeTarget", resetTime);
yield return null;
}
}
Here i attached Screenshot of Hirerchy & Inspector
Also i tried other different MovingPlatform Scripts but MovingPlatform's movement is jerky when player ride on it.
Only this script. MovingPlatform's movement is smooth when Player ride on it.
Anyone idea how to solve this?
Here is a little script without states, just a small coroutine to achieve what you want :
// Drag & Drop the platform gameobject
public Transform movingPlatform;
// Drag & Drop all the GameObjects (empty) the platform must go to
public Transform[] positions;
private void Awake()
{
StartCoroutine( Run() );
}
private IEnumerator Run( float duration = 5f, float waitTime = 3f )
{
int index = 0;
float time = 0;
WaitForSeconds wait = new WaitForSeconds( waitTime );
while( true )
{
Vector3 startPosition = positions[index].position;
Vector3 endPosition = positions[ (index + 1) % positions.Length].position;
for ( time = 0 ; time < duration ; time += Time.deltaTime )
{
movingPlatform.position = Vector3.Lerp( startPosition, endPosition, Mathf.SmoothStep( 0, 1, time ) );
yield return null;
}
movingPlatform.position = endPosition;
index = ( index + 1 ) % positions.Length;
yield return wait;
}
}
First of all create some enumeration for your platform/paddle state
enum PaddleState
{
Retargetting,
Moving,
Stationary
}
Now add some fields to your behaviour :
PaddleState paddleState = PaddleState.Stationary;
Vector3[] targets;
int currentTargetIdx = 0;
float stationaryFor = 0.0f;
Change your Update() method to only do certain logic when paddle is in the correct state :
void Update()
{
if(CheckState())
{
ChangeState();
}
}
void CheckState()
{
switch(paddleState)
{
case PaddleState.Retargetting: // choose new target and reset stationary timer
{
stationaryFor = 0.0f;
if(targets.Length >= currentTargetIdx)
{
currentTargetIdx = 0;
}
paddletarget = targets[currentTargetIdx++]; // post increment
return true;
}
case PaddleState.Moving: // move paddle and check the distance to target, if distance is less than x then go to the stationary state
{
paddle.position = Vector3.Lerp(paddle.position, targets[currentTargetIdx], smooth * Time.deltaTime);
return Vector3.Distance(paddle.position, targets[currentTargetIdx]) < 0.5f; // arbitrary distance
}
case PaddleState.Stationary: // do not move for 3 seconds
{
stationaryFor += Time.deltaTime;
return stationaryFor >= 3.0f;
}
}
}
void ChangeState()
{
// go to the next state
paddleState = (int)paddleState + 1 > PaddleState.Stationary ? PaddleState.Retargeting : (PaddleState)((int)paddleState + 1);
}

How do I get an object to move and swap places with another object, on a mouse clic

I have a script so far that moves an object a small distance upon a mouse click, however I want to change it so that when I click this object, it swaps places with another obejct next to it, instead of just the small distance it is moving now. I am a little confused on how to do this, because I am new to unity.
using UnityEngine;
using System.Collections;
public class NewBehaviourScript: MonoBehaviour
{
public float movementSpeed = 10;
void Update(){
if ( Input.GetMouseButtonDown(0))
{
transform.Translate(Vector3.right * movementSpeed * Time.deltaTime);
}
}
}
Try this:
using UnityEngine;
using System.Collections;
public class NewBehaviourScript: MonoBehaviour {
public GameObject objectA; //Needs to be initialized in the editor, or on Start
public GameObject objectB; //Needs to be initialized in the editor, or on Start
public float movementSpeed = 10;
private Vector3 posA = Vector3.zero; //Vector3.zero is for initialization
private Vector3 posB = Vector3.zero; //Vector3.zero is for initialization
void Update() {
if ( Input.GetMouseButtonDown(0)) {
posA = objectA.gameObject.transform.position;
posB = objectB.gameObject.transform.position;
objectA.gameObject.transform.position = posB;
objectB.gameObject.transform.position = posA;
}
}
}
This just saves each objects position into the posA and posB variables, then you move objectA to posB and objectB to posA.
-OR-
Now if objectB is always a different object (NOT constant) and you aren't sure how to find the nearest object, you could use a raycast. Add the following function to your code:
gamObject NearestObject () {
int dist;
int nearestIndex;
//Create an array to contain objects to be hit by the raycast
RaycastHit[] nearby;
//Hit all objects within 100 units with a raycast, change the 100 as needed
nearby = Physics.RaycastAll(objectA.transform.position, transform.forward, 100.0f);
//Check if there is at least one object
if(nearby.Length > 0) {
//If there is only one object and it's not objectA
if(!(nearby.Length == 1 && nearby[0].transform == objectA.transform)) {
dist = nearby[0].distance;
nearestIndex = 0;
for (int i = 1; i < nearby.Length; i++) {
if(nearby[i].transform != gameObject.transform && nearby[i].distance < dist)
dist = nearby[i].distance;
nearestIndex = i;
}
}
} else {
//There is only one object in the raycast and it is objectA
nearestIndex = -1;
}
} else {
//There are no objects nearby
nearestIndex = -1;
}
//nearestIndex will only be negative one if there are no objects near objectA, so return null
if (nearestIndex == -1) {
return null;
} else {
//return nearest object to update
return nearby[nearestIndex].gameObject;
}
}
Finally, change Update to:
void Update() {
if ( Input.GetMouseButtonDown(0)) {
objectB = NearestObject ();
if (objectB != null) {
posA = objectA.gameObject.transform.position;
posB = objectB.gameObject.transform.position;
objectA.gameObject.transform.position = posB;
objectB.gameObject.transform.position = posA;
}
}
}
using UnityEngine;
using System.Collections;
public class NewBehaviourScript : MonoBehaviour
{
//making them public just to be able watch values change in game mode
public float movementSpeed = 10;
public GameObject g1;
public GameObject g2;
public Vector3 vec1;
public Vector3 vec2 = new Vector3(2F, 2F, 2F);
public bool swapBack = false;
void Start()
{
g1 = GameObject.Find("Cube");
g2 = GameObject.Find("Sphere");
vec1 = new Vector3(g1.gameObject.transform.position.x, g1.gameObject.transform.position.y, g1.gameObject.transform.position.z);
vec2 = new Vector3(g2.gameObject.transform.position.x, g2.gameObject.transform.position.y, g2.gameObject.transform.position.z);
}
void Update()
{
if (Input.GetMouseButtonDown(0))
{
transform.Translate(Vector3.right * movementSpeed * Time.deltaTime);
swap(swapBack);
}
}
public void swap(bool back)
{
if (back)
{
g1.transform.position = vec1;
g2.transform.position = vec2;
swapBack = false;
}
else
{
g1.transform.position = vec2;
g2.transform.position = vec1;
swapBack = true;
}
}
}

Unity2D: How to make spawn object gradually go faster after the player collects 10 points?

so I was wondering if there was a way to make a spawned object gradually moves/go faster after the player (you the user) collects 10 points. And faster when the player collects another 10 points and so on and so on?
This is my movement script attach to my objects that get spawned in:
public class Movement : MonoBehaviour
{
public static int movespeed = 20;
public Vector3 userDirection = Vector3.right;
public void Update()
{
transform.Translate(userDirection * movespeed * Time.deltaTime);
}
}
This is my score script attach to my player
public int Score;
public Text ScoreText;
void Start ()
{
Score = 0;
SetScoreText ();
}
void OnTriggerEnter2D(Collider2D other)
{
if (other.gameObject.CompareTag ("Pick Up"))
{
other.gameObject.SetActive (false);
Score = Score + 1;
SetScoreText ();
}
}
void SetScoreText ()
{
ScoreText.text = "Score: " + Score.ToString ();
}
And this is my generateEnemy script:
public GameOverManager gameOverManager = null;
[HideInInspector]
public float minBlobSpawnTime = 2;
[HideInInspector]
public float maxBlobSpawnTime = 5;
[HideInInspector]
public bool generateBlobs = true;
[HideInInspector]
public GameObject blobPrefab = null;
[HideInInspector]
public GameObject blobRoot = null;
[HideInInspector]
public float minimumYPosition = -0.425f;
[HideInInspector]
public float maximumYPosition = 0.35f;
[HideInInspector]
public float minDaggerSpawnTime = 2;
[HideInInspector]
public float maxDaggerSpawnTime = 5;
[HideInInspector]
public bool generateDaggers = true;
[HideInInspector]
public GameObject daggerPrefab = null;
[HideInInspector]
public GameObject daggerRoot;
[HideInInspector]
public float minimumXPosition = -11.5f;
[HideInInspector]
public float maximumXPosition = 11.5f;
public Camera camera = null;
// Use this for initialization
void Start ()
{
generateBlobs = ((generateBlobs) && (blobPrefab != null) && (blobRoot != null));
generateDaggers = ((generateDaggers) && (daggerPrefab != null) && (daggerRoot != null));
if (camera == null)
{
Debug.LogError("GenerateEnemy: camera is not set in the inspector. Please set and try again.");
camera = Camera.main;
}
if (gameOverManager == null)
{
Debug.LogError("GenerateEnemy: gameOverManager not set in the inspector. Please set and try again.");
}
if (generateBlobs)
{
StartCoroutine(GenerateRandomEnemy(true, blobPrefab, blobRoot, minBlobSpawnTime, maxBlobSpawnTime));
}
if (generateDaggers)
{
StartCoroutine(GenerateRandomEnemy(false, daggerPrefab, daggerRoot, minDaggerSpawnTime, maxDaggerSpawnTime));
}
}
// Update is called once per frame
void Update ()
{
DestroyOffScreenEnemies();
}
// Spawn an enemy
IEnumerator GenerateRandomEnemy(bool generateOnYAxis, GameObject prefab, GameObject root, float minSpawnTime, float maxSpawnTime)
{
if ((prefab != null) && (gameOverManager != null))
{
if (!gameOverManager.GameIsPaused())
{
GameObject newEnemy = (GameObject) Instantiate(prefab);
newEnemy.transform.SetParent(root.transform, true);
// set this in the prefab instead
// newEnemy.transform.position = new Vector3(newEnemy.transform.parent.position.x, 0.5f, newEnemy.transform.parent.position.z);
// or if you want the y position to be random you need to do something like this
if (generateOnYAxis)
{
newEnemy.transform.position = new Vector3(newEnemy.transform.parent.position.x, Random.Range(minimumYPosition, maximumYPosition), newEnemy.transform.parent.position.z);
}
else
{
newEnemy.transform.position = new Vector3(Random.Range(minimumXPosition, maximumXPosition), newEnemy.transform.parent.position.y, newEnemy.transform.parent.position.z);
}
}
}
yield return new WaitForSeconds(Random.Range(minSpawnTime, maxSpawnTime));
StartCoroutine(GenerateRandomEnemy(generateOnYAxis, prefab, root, minSpawnTime, maxSpawnTime));
}
public void DestroyOffScreenEnemies()
{
GameObject[] enemies = GameObject.FindGameObjectsWithTag("enemy");
if ((enemies.Length > 0) && (camera != null))
{
for (int i = (enemies.Length - 1); i >= 0; i--)
{
// just a precaution
if ((enemies[i] != null) && ((camera.WorldToViewportPoint(enemies[i].transform.position).x > 1.03f) ||
(enemies[i].transform.position.y < -6f)))
{
Destroy(enemies[i]);
}
}
}
}
}
(This script has an generateEnemyCustomEditor script that references it, to show in the inspector)
Thank you :)
First of all, remove the static keyword from public static int movespeed = 20; and use GameObject.Find("ObjectMovementIsAttachedTo").GetComponent<Movement>(); to get the script instance if you want to modify movespeed variable from another script.
And faster when the player collects another 10 points and so on and so
on?
The solution is straight on. Use
if (Score % 10 == 0){
//Increement by number (4) movespeed from Movement script
movement.movespeed += 4;
}
to check if the Score is increased by 10 then increment movespeed by any value you want if that condition is true. It makes sense to put that in the OnTriggerEnter2D function after Score is incremented by 1.
Your new score script:
public class score : MonoBehaviour
{
public int Score;
public Text ScoreText;
private int moveSpeed;
void Start()
{
Score = 0;
SetScoreText();
}
void OnTriggerEnter2D(Collider2D other)
{
if (other.gameObject.CompareTag("Pick Up"))
{
other.gameObject.SetActive(false);
Score = Score + 1;
if (Score % 10 == 0)
{
//Increement by number (4) movespeed from Movement script
moveSpeed += 4;
}
SetScoreText();
}
}
public int getMoveSpeed()
{
return moveSpeed;
}
void SetScoreText()
{
ScoreText.text = "Score: " + Score.ToString();
}
}
Since your Movement script will be instantiated, when you instantiate it, you send its reference to the Player script.
public class Movement : MonoBehaviour
{
public int movespeed = 20;
public Vector3 userDirection = Vector3.right;
score mySpeed;
void Start()
{
//Send Movement instance to the score script
GameObject scoreGameObject = GameObject.Find("GameObjectScoreIsAttachedTo");
mySpeed = scoreGameObject.GetComponent<score>();
}
public void Update()
{
transform.Translate(userDirection * mySpeed.getMoveSpeed() * Time.deltaTime);
}
}

Categories