Issue with invokerepeating function in unity - c#

OK I have two scripts the first one is using invokerepeating to spawn obstacles at a given rate. The second script increases the speed of the obstacles every 20 seconds. My issue is that once the speed increases the gap between the obstacles increases which leads to very big gaps between each one. Any ideas on how to fix this?
using UnityEngine;
using System.Collections;
public class Generate : MonoBehaviour
{
public Vector3 startPosition;
public GameObject object1;
public GameObject object2;
public GameObject object3;
public int random;
int score = 0;
public int count = 0;
private float timeLeft = 20.0f;
private int num1 =3;
private int num2 =3;
// Use this for initialization
void Start()
{
startPosition = new Vector3(5, 0, 0);
random = Random.Range(1, 4);
InvokeRepeating("CreateObstacle", num1, num2);
}
// Update is called once per frame
/*void OnGUI ()
{
GUI.color = Color.black;
GUILayout.Label(" Score: " + score.ToString());
}*/
void Update(){
fast ();
}
void CreateObstacle()
{
if (random == 1) {
GameObject go = Instantiate(object1, startPosition, Quaternion.identity) as GameObject;
go.transform.parent = GameObject.Find("4 - Obstacles").transform;
random = Random.Range(1, 4);
//Destroy(gameObject, 10);
}
else if (random == 2) {
GameObject go = Instantiate(object2, startPosition, Quaternion.identity) as GameObject;
go.transform.parent = GameObject.Find("4 - Obstacles").transform;
random = Random.Range(1, 4);
//Destroy(gameObject, 10);
}
else if(random == 3) {
GameObject go = Instantiate(object3, startPosition, Quaternion.identity) as GameObject;
go.transform.parent = GameObject.Find("4 - Obstacles").transform;
random = Random.Range(1, 4);
//Destroy(gameObject, 10);
}
}
void fast(){
//Timer
timeLeft -= Time .deltaTime;
if (timeLeft <= 0.0f) {
count ++;
timeLeft += 20.0f;
num1 += 1;
num2 += 1;
}
if (count == 1) {
num1 += 1;
num2 += 1;
count ++;
}
else if (count == 3) {
num1 += 1;
num2 += 1;
count ++;
}
}
void OnGUI () {
// Make a background box
GUI.Box (new Rect (10, 10, 100, 90), "Number" + num1);
}
}
second script
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
/// <summary>
/// Parallax scrolling script that should be assigned to a layer
/// </summary>
public class Scrolling : MonoBehaviour
{
public int count = 0;
private float timeLeft = 20.0f;
/// <summary>
/// Scrolling speed
/// </summary>
private Vector2 speed = new Vector2(2, 2);
/// <summary>
/// Moving direction
/// </summary>
public Vector2 direction = new Vector2(-1, 0);
/// <summary>
/// Movement should be applied to camera
/// </summary>
public bool isLinkedToCamera = false;
/// <summary>
/// 1 - Background is infinite
/// </summary>
public bool isLooping = false;
/// <summary>
/// 2 - List of children with a renderer.
/// </summary>
private List<Transform> backgroundPart;
// 3 - Get all the children
void Start()
{
// For infinite background only
if (isLooping)
{
// Get all the children of the layer with a renderer
backgroundPart = new List<Transform>();
for (int i = 0; i < transform.childCount; i++)
{
Transform child = transform.GetChild(i);
// Add only the visible children
if (child.renderer != null)
{
backgroundPart.Add(child);
}
}
// Sort by position.
// Note: Get the children from left to right.
// We would need to add a few conditions to handle
// all the possible scrolling directions.
backgroundPart = backgroundPart.OrderBy(
t => t.position.x
).ToList();
}
}
void Update()
{
//InvokeRepeating("fast", 1, 1);
fast();
// Movement
Vector3 movement = new Vector3(
speed.x * direction.x,
speed.y * direction.y,
0);
movement *= Time.deltaTime;
transform.Translate(movement);
// Move the camera
if (isLinkedToCamera)
{
Camera.main.transform.Translate(movement);
}
// 4 - Loop
if (isLooping)
{
// Get the first object.
// The list is ordered from left (x position) to right.
Transform firstChild = backgroundPart.FirstOrDefault();
if (firstChild != null)
{
// Check if the child is already (partly) before the camera.
// We test the position first because the IsVisibleFrom
// method is a bit heavier to execute.
if (firstChild.position.x < Camera.main.transform.position.x)
{
// If the child is already on the left of the camera,
// we test if it's completely outside and needs to be
// recycled.
if (firstChild.renderer.IsVisibleFrom(Camera.main) == false)
{
// Get the last child position.
Transform lastChild = backgroundPart.LastOrDefault();
Vector3 lastPosition = lastChild.transform.position;
Vector3 lastSize = (lastChild.renderer.bounds.max - lastChild.renderer.bounds.min);
// Set the position of the recyled one to be AFTER
// the last child.
// Note: Only work for horizontal scrolling currently.
firstChild.position = new Vector3(lastPosition.x + lastSize.x, firstChild.position.y, firstChild.position.z);
// Set the recycled child to the last position
// of the backgroundPart list.
backgroundPart.Remove(firstChild);
backgroundPart.Add(firstChild);
}
}
}
}
}
void fast(){
//Timer
timeLeft -= Time .deltaTime;
if (timeLeft <= 0.0f) {
count ++;
timeLeft += 20.0f;
speed.x += 0.4f;
speed.y += 0.4f;
}
if (count == 1) {
speed.x += 0.4f;
speed.y += 0.4f;
count ++;
}
else if (count == 3) {
speed.x += 0.4f;
speed.y += 0.4f;
count ++;
}
/* else if (count == 5) {
speed.x ++;
speed.y ++;
count ++;
}*/
else if (count == 5) {
speed.x += 5;
speed.y += 5;
count ++;
}
}
void OnGUI ()
{
GUI.color = Color.black;
GUILayout.Label(" Speed: " + speed.ToString() + " Count: " + count.ToString ());
GUILayout.Label(" Time: " + timeLeft.ToString());
}
}

You will also have to reduce the time with which the obstacles are generating (which you are trying in your fast() method but it will not work). You are updating your num1 and num2 values but these values are never assigned to the InvokeRepeating.
After updating your num1 and num2 also cancel the previous invoke and create a new invoke (I believe this time you will only need num2). Add these two lines at the end of your fast() method.
CancelInvoke("CreateObstacle");
InvokeRepeating("CreateObstacle", num2, num2);
First time value in InvokeRepeating defines how long to wait before calling the method for the first. Second time value defines the duration after which method calls will be repeated. (In short first value is used only for first time and second value is used for repeated method calls).

Related

How to display Text during Unity game?

I inherited by my ex collegue a Unity game. I need to display a label in my scene. The label should be contains the text "what is your level of fear?"
The user should be throught Logitech steering wheel, using the rotation button select a number from 0 to 9.
Now I m new user of unity and I want to start this task step by step. My Unity project have a Init scene that can start other scenes.
In my Init scene I create this static component (FearTest):
This component have a RedDot (a simple red dot) and textAnsia2 that contains the text that I need to display.
This is my class FreatTest:
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.SceneManagement;
namespace DrivingTest
{
public class FearTest : MonoBehaviour
{
//public GameObject redDot;
public TextMeshPro textAnsia2;
public TextMesh textAnsia3;
public int shouldEvaluateTest = 0; // 0 - false, 1 - true
public int secondsInterval;
public int secondsToDisaply;
public int radiusR1;
public int radiusR2;
public int reactionTestDuration;
public int maxDots;
public float dotRadius = 1;
private float endTime;
private float dotDisaplyAtTime;
private List<float> dotDisplayReactTime = new List<float>();
private int missedSignals;
private int currentDotsCount;
private bool isReactionAlreadyGiven;
public bool ShouldEvaluateTest
{
get
{
return shouldEvaluateTest != 0;
}
}
void OnEnable()
{
GameManager.TestSceneLoaded += OnSceneLoaded;
}
private void OnDisable()
{
GameManager.TestSceneLoaded -= OnSceneLoaded;
}
#region Scene Loaded
private void OnSceneLoaded(eTESTS test)
{
if (SceneManager.GetActiveScene().name != test.ToString())
return;
Reset();
GetApiParams();
}
#endregion
private void GetApiParams()
{
#if UNITY_EDITOR
if (!GameManager.Instance)
{
Init();
return;
}
#endif
Debug.Log("called rt");
NextTestOutput nextTestOutput = GameManager.Instance.currentTest;
if (nextTestOutput.content != null && nextTestOutput.content.Count > 0)
{
foreach (var item in nextTestOutput.content[0].listInputParameter)
{
switch ((ePARAMETERS)item.id)
{
case ePARAMETERS.RT_ENABLE:
shouldEvaluateTest = System.Convert.ToInt32(item.Value);
break;
case ePARAMETERS.RT_DURATION:
reactionTestDuration = System.Convert.ToInt32(item.Value);
break;
case ePARAMETERS.RED_DOT_FREQ:
secondsInterval = System.Convert.ToInt32(item.Value);
break;
case ePARAMETERS.RED_DOT_MAX_COUNT:
maxDots = System.Convert.ToInt32(item.Value);
break;
case ePARAMETERS.RED_DOT_RADIUS_R1:
radiusR1 = System.Convert.ToInt32(item.Value);
break;
case ePARAMETERS.RED_DOT_RADIUS_R2:
radiusR2 = System.Convert.ToInt32(item.Value);
break;
case ePARAMETERS.RED_DOT_SIZE:
dotRadius = float.Parse(item.Value)/10f;
break;
case ePARAMETERS.RED_DOT_TIME:
secondsToDisaply = System.Convert.ToInt32(item.Value);
break;
}
}
Debug.Log("called rt "+ shouldEvaluateTest);
/*if (ShouldEvaluateTest)
{
Init();
}*/
Init();//dopo bisogna sistemare il shoudl evaluatetest
}
}
Coroutine displayCoroutine;
public void Init()
{
endTime = Time.time + reactionTestDuration + 10;
SetRedDotSize();
displayCoroutine = StartCoroutine(RedDotDisplay());
}
private IEnumerator RedDotDisplay()
{
yield return new WaitForSeconds(2);
while (true)
{
SetRandomDotPosition();
RedDot(true);
isReactionAlreadyGiven = false;
dotDisaplyAtTime = Time.time;
currentDotsCount++;
yield return new WaitForSeconds(secondsToDisaply);
if(!isReactionAlreadyGiven)
{
missedSignals++;
}
RedDot(false);
if ((reactionTestDuration > 0 && endTime <= Time.time) || (maxDots > 0 && currentDotsCount >= maxDots))
break;
float waitTime = secondsInterval - secondsToDisaply;
yield return new WaitForSeconds(waitTime);
}
}
private void Update()
{
if (!ShouldEvaluateTest)
return;
if (!isReactionAlreadyGiven && /*redDot.activeSelf &&*/ (LogitechGSDK.LogiIsConnected(0) && LogitechGSDK.LogiButtonIsPressed(0, 23)))
{
isReactionAlreadyGiven = true;
float reactionTime = Time.time - dotDisaplyAtTime;
Debug.Log("Reaction Time RT : " + reactionTime);
RedDot(false);
dotDisplayReactTime.Add(reactionTime);
}
}
public double GetReactionTimeAvg()
{
double avg = 0;
foreach (var item in dotDisplayReactTime)
{
avg += item;
}
//avg / currentDotsCount
return avg / (float)dotDisplayReactTime.Count;
}
public double GetMissedSignals()
{
return ((float) missedSignals / (float) currentDotsCount) * 100;
}
private void RedDot(bool state)
{
//redDot.SetActive(state);
textAnsia2.SetText("Pippo 2");
}
private void SetRedDotSize()
{
//redDot.transform.localScale *= dotRadius;
textAnsia2.transform.localScale *= dotRadius;
textAnsia3.transform.localScale *= dotRadius;
}
private void SetRandomDotPosition()
{
//redDot.GetComponent<RectTransform>().anchoredPosition = GetRandomPointBetweenTwoCircles(radiusR1, radiusR2)*scale;
float scale = ((Screen.height*0.9f) / radiusR2) * 0.9f;
Vector3 pos = GetRandomPointBetweenTwoCircles(radiusR1, radiusR2) * scale;
Debug.Log("RT temp pos : " + pos);
pos = new Vector3(500, 500, 0);
Debug.Log("RT pos : " + pos);
// redDot.transform.position = pos;
Vector3 pos2 = new Vector3(20, 20, 0);
Debug.Log("text ansia 2 : " + pos2);
textAnsia2.transform.position = pos2;
textAnsia3.transform.position = pos;
}
#region Getting Red Dot b/w 2 cricles
/*
Code from : https://gist.github.com/Ashwinning/89fa09b3aa3de4fd72c946a874b77658
*/
/// <summary>
/// Returns a random point in the space between two concentric circles.
/// </summary>
/// <param name="minRadius"></param>
/// <param name="maxRadius"></param>
/// <returns></returns>
Vector3 GetRandomPointBetweenTwoCircles(float minRadius, float maxRadius)
{
//Get a point on a unit circle (radius = 1) by normalizing a random point inside unit circle.
Vector3 randomUnitPoint = Random.insideUnitCircle.normalized;
//Now get a random point between the corresponding points on both the circles
return GetRandomVector3Between(randomUnitPoint * minRadius, randomUnitPoint * maxRadius);
}
/// <summary>
/// Returns a random vector3 between min and max. (Inclusive)
/// </summary>
/// <returns>The <see cref="UnityEngine.Vector3"/>.</returns>
/// <param name="min">Minimum.</param>
/// <param name="max">Max.</param>
Vector3 GetRandomVector3Between(Vector3 min, Vector3 max)
{
return min + Random.Range(0, 1) * (max - min);
}
#endregion
#region Reset
private void Reset()
{
if (displayCoroutine != null)
StopCoroutine(displayCoroutine);
RedDot(false);
shouldEvaluateTest = 0;
reactionTestDuration = 0;
secondsInterval = 0;
missedSignals = 0;
maxDots = 0;
radiusR1 = 0;
radiusR2 = 0;
dotRadius = 1;
secondsToDisaply = 0;
endTime = 0;
dotDisaplyAtTime = 0;
dotDisplayReactTime.Clear();
//redDot.transform.localScale = Vector3.one;
textAnsia2.transform.localScale = Vector3.one;
textAnsia3.transform.localScale = Vector3.one;
currentDotsCount = 0;
isReactionAlreadyGiven = true;
}
#endregion
}
}
When "SetRandomDotPosition" method is called, in my scene I can display in a random position of the screen the RedDot (that is a simple image with a red dot), and I need to display also my text.
The red dot is displayed, but I m not able to display the text.
How can I fixed it ?

How can I change the code that if the goForward state change in runtime or at start move the transform forward or backward?

using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
public class WaypointsFollower : MonoBehaviour
{
public float speed;
public Waypoints waypoints;
public bool go;
public bool goForward;
private int index = 0;
private int counter = 0;
private int c = 0;
private List<GameObject> curvedLinePoints = new List<GameObject>();
public int numofposbetweenpoints;
private bool getonce;
private void Start()
{
waypoints = GameObject.Find("Waypoints").GetComponent<Waypoints>();
curvedLinePoints = GameObject.FindGameObjectsWithTag("Curved Line Point").ToList();
}
private void Update()
{
if (getonce == false)
{
numofposbetweenpoints = curvedLinePoints.Count;
getonce = true;
}
if (go == true && waypoints.lineRendererPositions.Count > 0)
{
Move();
}
}
private void Move()
{
Vector3 newPos = transform.position;
float distanceToTravel = speed * Time.deltaTime;
bool stillTraveling = true;
while (stillTraveling)
{
Vector3 oldPos = newPos;
// error exception out of bound on line 55 to check !!!!!
newPos = Vector3.MoveTowards(oldPos, waypoints.lineRendererPositions[index], distanceToTravel);
distanceToTravel -= Vector3.Distance(newPos, oldPos);
if (newPos == waypoints.lineRendererPositions[index]) // Vector3 comparison is approximate so this is ok
{
// when you hit a waypoint:
if (goForward)
{
bool atLastOne = index >= waypoints.lineRendererPositions.Count - 1;
if (!atLastOne)
{
index++;
counter++;
if (counter == numofposbetweenpoints)
{
c++;
counter = 0;
}
if (c == curvedLinePoints.Count - 1)
{
c = 0;
}
}
else { index--; goForward = false; }
}
else
{ // going backwards:
bool atFirstOne = index <= 0;
if (!atFirstOne)
{
index--;
counter++;
if (counter == numofposbetweenpoints)
{
c++;
counter = 0;
}
if (c == curvedLinePoints.Count - 1)
{
c = 0;
}
}
else { index++; goForward = true; }
}
}
else
{
stillTraveling = false;
}
}
transform.position = newPos;
}
}
Now it's moving from the first index to the last one then when reaching the last index it's moving from the last index to the first one and so on nonstop.
but I want that if goForward is true at the start to go to the first index to the last then from last to the first like it is now but if goForward will be false at the start then start from the last index move in reverse to the first index and then from the first index to the last same as the first state but opposite.
and if I change the goForward at run time then change the transform moving direction to the last/before index it was and keep moving on that direction. and if I change the flag at a run time again change direction again so I can change the direction/s in real time.
How can I change the code that if the goForward state change in runtime or at start move the transform forward or backward?
Consider using the mathematical %(modulo) operator. This operator performs 'clock math'. Think of it like a hand on a clock, when it reaches 12 on the clock the hand 'wraps around' the the beginning and starts as 1. Take the number 4 for example. If we have a loop like
for(int i = 0; i < 8; i++)
{
Console.WriteLine($"{i % 4}");
}
It would produce 0, 1, 2, 3, 0, 1, 2, 3. This in-effect gives you a looping index around the number 4.
If we look at this in the context of an array(or list) we can loop through an array, forwards AND backwards without ever checking to see if we are at the first or last position of the array(or list).
This effect is super helpful for traveling between arbitrary waypoints and avoiding that pesky IndexOutOfBoundsException.
You could implement something like this to achieve the effect you want:
private void Move()
{
Vector3 newPos = transform.position;
float distanceToTravel = speed * Time.deltaTime;
bool stillTraveling = true;
while (stillTraveling)
{
Vector3 oldPos = newPos;
// error exception out of bound on line 55 to check !!!!!
newPos = Vector3.MoveTowards(oldPos, waypoints.lineRendererPositions[index], distanceToTravel);
distanceToTravel -= Vector3.Distance(newPos, oldPos);
if (newPos == waypoints.lineRendererPositions[index]) // Vector3 comparison is approximate so this is ok
{
// determine if we should go forward or backward through the list
int direction = goForward ? 1 : -1;
// loop around the index, this automatically wraps to 0 if we are going forward and get to the end of the list,
// or to the end if we are going backwards and hit the end of the list
index = (index + direction) % waypoints.lineRendererPositions.Count;
// increment the amounnt of points we passed
counter++;
if (counter == numofposbetweenpoints)
{
c++;
counter = 0;
}
// reset C if we reached the end
if (c == curvedLinePoints.Count - 1)
{
c = 0;
}
}
else
{
stillTraveling = false;
}
}
transform.position = newPos;
}

Array inaccessible only at certain times

I am currently building a parallax background effect in Unity and starting with some starter code that I'm trying to work though. The code works for the most part, with some small issues I'm slowly getting through.
I have been testing out various stats of public vs. private, etc. but can't seem to work out exactly why and where the issue I'm facing is occurring.
When I run the same script and it calls Update() every frame, I would expect to have the same size "poolObjects" length. However, when I call it with a starting pool size of 10, I get 10, then 2, then 0, then 10, 2, 0, etc.
I am truncating it but posting what I think to be relevant here. Hope you can help me see what is likely obvious!
I do see "In GetPool Object" but because the length is never > 0, I never see within the For Loop, which is essential. I can't figure out why the poolObjects length would be showing up as 0.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Parallaxer : MonoBehaviour {
class PoolObject {
public Transform transform;
public bool inUse;
public PoolObject(Transform t) { transform = t; }
public void Use() { inUse = true; }
public void Dispose() { inUse = false; }
}
...
public int poolSize;
public float shiftSpeed;
public float spawnRate;
...
float spawnTimer;
PoolObject[] poolObjects;
float targetAspect;
GameManager game;
void Awake() {
Configure();
}
void Start() {
game = GameManager.Instance;
}
...
void Update() {
Debug.Log(poolObjects.Length + "Len here of pool objects");
if (game.GameOver) return;
Shift();
spawnTimer += Time.deltaTime;
if (spawnTimer > spawnRate) {
Spawn();
spawnTimer = 0;
}
}
void Configure() {
//spawning pool objects
targetAspect = targetAspectRatio.x / targetAspectRatio.y;
// targetAspect = Camera.main.aspect;
// Debug.Log(targetAspectRatio.x +" " + targetAspectRatio.y);
poolObjects = new PoolObject[poolSize];
for (int i = 0; i < poolObjects.Length; i++) {
GameObject go = Instantiate(Prefab) as GameObject;
Transform t = go.transform;
t.SetParent(transform);
t.position = Vector3.one * 1000;
poolObjects[i] = new PoolObject(t);
}
if (spawnImmediate) {
SpawnImmediate();
}
}
void Spawn() {
//moving pool objects into place
Transform t = GetPoolObject();
Debug.Log("In to Spawn" + t);
if (t == null) return;
Vector3 pos = Vector3.zero;
pos.y = Random.Range(ySpawnRange.minY, ySpawnRange.maxY);
pos.x = (defaultSpawnPos.x * Camera.main.aspect) / targetAspect;
// Debug.Log("Spwaning");
// Debug.Log(Camera.main.aspect);
// Debug.Log(immediateSpawnPos.x + " " + immediateSpawnPos.y + " " + targetAspect);
t.position = pos;
// Debug.Log(pos);
}
void SpawnImmediate() {
Transform t = GetPoolObject();
if (t==null) return;
Vector3 pos = Vector3.zero;
pos.y = Random.Range(ySpawnRange.minY, ySpawnRange.maxY);
pos.x = (immediateSpawnPos.x * Camera.main.aspect) / targetAspect;
t.position = pos;
Spawn();
}
void Shift() {
//loop through pool objects
//moving them
//discarding them as they go off screen
Debug.Log(poolObjects.Length + "Finding Length");
for (int i = 0; i < poolObjects.Length; i++) {
poolObjects[i].transform.position += -Vector3.right * shiftSpeed * Time.deltaTime;
Debug.Log(poolObjects[i].transform.position);
CheckDisposeObject(poolObjects[i]);
}
}
void CheckDisposeObject(PoolObject poolObject) {
//place objects off screen
if (poolObject.transform.position.x < (-defaultSpawnPos.x * Camera.main.aspect) / targetAspect) {
poolObject.Dispose();
poolObject.transform.position = Vector3.one * 1000;
}
}
Transform GetPoolObject() {
//retrieving first available pool object
Debug.Log("In GetPool Object" + poolObjects.Length);
for (int i = 0; i < poolObjects.Length; i++) {
Debug.Log("This is not showing up "+ poolObjects[i].inUse);
if (!poolObjects[i].inUse) {
poolObjects[i].Use();
return poolObjects[i].transform;
}
}
return null;
}
}

Unity C# Input.GetMouseDown(1) only happening once in update function

so i've been working on some code for a game in Unity and i am using the Input.GetMouseButtonDown(1) function. However, it only works the first time i press the left click in the game and no other times after that. The code for the player controller where it's used is below:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class PlayerController : MonoBehaviour {
public float speed;
public Transform enemy;
public Transform shot;
public GameObject shotObj;
public Text scoreT;
public Text timeT;
public Text roundT;
public float health;
public float damageTaken;
public Vector3 lookPoint;
public float shotSpeed;
private Camera mainCamera;
private int round = 1;
private int tempRound = 0;
private float time = 300;
private bool win = false;
private bool allowShoot;
private EnemyController enemyScript;
private ShotController shotScript;
private bool tempImune = false;
private int targetTime;
private int score = 0;
private int defeatedEnemy = 0;
private GameObject enemyObj;
//coroutine
IEnumerator Pause(float timE)
{
allowShoot = false;
//time since the object was created
float start = Time.realtimeSinceStartup;
//sets the game to slow down to 0 movement
Time.timeScale = 0.0f;
//loops until start up time is less than start time + pause time
while (Time.realtimeSinceStartup < start + timE)
{
//returns null from the subroutine and restarts the subroutine at this point after null (0) time has passed
yield return null;
}
//sets the gamne to be running at normal speed
Time.timeScale = 1.0f;
allowShoot = true;
if (timE == 5.0f)
{
roundT.gameObject.SetActive(false);
}
}
void Start () {
//center mouse
Cursor.lockState = CursorLockMode.Locked;
Cursor.lockState = CursorLockMode.None;
//set camera to be the camera in the scene (should only ever be one camera in the scene)
mainCamera = FindObjectOfType<Camera>();
//set default text values
scoreT.text = "Score: 000000";
timeT.text = "Time Left: 600";
roundT.text = "Round: " + round;
//pause game before first round begins
StartCoroutine(Pause(5.0f));
}
void Update () {
//looka at mouse script
Ray cameraRay = mainCamera.ScreenPointToRay(Input.mousePosition);
Plane ground = new Plane(Vector3.up, Vector3.zero);
float rayLength;
if (ground.Raycast(cameraRay, out rayLength))
{
lookPoint = cameraRay.GetPoint(rayLength);
transform.LookAt(new Vector3(lookPoint.x, transform.position.y, lookPoint.z));
}
//enemy spawner check and win criteria check
if (defeatedEnemy != 45)
{
if (round != tempRound)
{
spawnEnemy();
roundT.gameObject.SetActive(true);
if (round == 5)
{
roundT.text = "Round: " + round + "(Final Round)";
}
else
{
roundT.text = "Round: " + round;
}
StartCoroutine(Pause(5.0f));
}
}
else
{
win = true;
}
//timer and win check
if (health == 0f)
{
win = true;
}
if (!win)
{
time -= Time.deltaTime;
timeT.text = "Time Left: " + time;
}
else
{
if (health == 0f)
{
roundT.gameObject.SetActive(true);
int finalScore = Mathf.RoundToInt(score * ((time / 2) / 10));
roundT.text = "To Bad, You Loose! Score = " + finalScore;
Debug.Log(finalScore);
StartCoroutine(Pause(99999f));
}
else
{
roundT.gameObject.SetActive(true);
int finalScore = Mathf.RoundToInt(score * ((time / 2) / 10));
roundT.text = "Congratulations! Score = " + finalScore;
Debug.Log(finalScore);
}
}
//movement controlls
if (Input.GetKey(KeyCode.W) || Input.GetKey(KeyCode.UpArrow))
{
transform.Translate(new Vector3(0.0f, 0.0f, speed * Time.deltaTime));
}
if (Input.GetKey(KeyCode.A) || Input.GetKey(KeyCode.LeftArrow))
{
transform.Translate(new Vector3(-speed * Time.deltaTime, 0.0f, 0.0f));
}
if (Input.GetKey(KeyCode.S) || Input.GetKey(KeyCode.DownArrow))
{
transform.Translate(new Vector3(0.0f, 0.0f, -speed * Time.deltaTime));
}
if (Input.GetKey(KeyCode.D) || Input.GetKey(KeyCode.RightArrow))
{
transform.Translate(new Vector3(speed * Time.deltaTime, 0.0f, 0.0f));
}
//shoot controll
if (allowShoot)
{
Debug.Log("shot allowed");
if (Input.GetMouseButtonDown(0))
{
//var spawnShot = Instantiate(shot, this.transform.position + new Vector3(0.0f, 0.0f, 0.5f), this.transform.rotation);
//shotScript = shotObj.GetComponent<ShotController>();
//if (shotScript.enemy)
//{
// Debug.Log("enemy found");
// enemyScript = shotScript.enemy.GetComponent<EnemyController>();
// if(enemyScript.health <= 0.0f)
// {
// score += 20;
// defeatedEnemy += 1;
// scoreT.text = "Score: " + score;
// Debug.Log("enemy killed : " + defeatedEnemy);
// }
//}
Debug.Log("mouseDown");
int layermask = 1 << 8;
RaycastHit hit;
if (Physics.Raycast(transform.position, transform.TransformDirection(Vector3.forward), out hit, Mathf.Infinity, layermask))
{
enemyObj = hit.transform.gameObject;
enemyScript = enemyObj.GetComponent<EnemyController>();
Debug.Log("hit");
//hit.transform.SendMessage("HitByRay");
if (enemyScript.health == 0f)
{
Destroy(hit.transform.gameObject);
score += 20;
defeatedEnemy += 1;
scoreT.text = "Score: " + score;
Debug.Log("enemy killed : " + defeatedEnemy);
}
}
}
}
//enemy existance check
if (GameObject.Find("Enemy(Clone)") == null)
{
round = round + 1;
}
if (tempImune)
{
if (Mathf.RoundToInt(time) == targetTime)
{
tempImune = false;
}
}
}
void spawnEnemy()
{
tempRound = round;
for (int i = 1; i <= round * 3; i++)
{
var spawnEnemy = Instantiate(enemy, new Vector3(Random.Range(-14.5f, 14.5f), 0.25f, Random.Range(-6f, 6f)), Quaternion.identity);
}
}
void OnCollisionEnter(Collision col)
{
if (col.gameObject.tag == "Enemy")
{
if (!tempImune)
{
health = health - damageTaken;
Debug.Log(health);
tempImune = true;
targetTime = Mathf.RoundToInt(time) - 1;
}
}
}
}
Any help with this would be greatly appreciated as it's for a school project. Thanks.
You need to call this function from the Update function, since the state gets reset each frame. It will not return true until the user has released the mouse button and pressed it again. button values are 0 for the primary button (often the left button), 1 for secondary button, and 2 for the middle button
using UnityEngine;
using System.Collections;
public class ClassName : MonoBehaviour
{
void Update()
{
if (Input.GetMouseButtonDown(0))
Debug.Log("Pressed primary button.");
if (Input.GetMouseButtonDown(1))
Debug.Log("Pressed secondary button.");
if (Input.GetMouseButtonDown(2))
Debug.Log("Pressed middle click.");
}
}

objects using their own unique waypoints array

update...
First Class
using UnityEngine;
using System.Collections;
[System.Serializable]
public class Wave
{
public GameObject enemyPrefab;
public float spawnInterval = 2;
public int maxEnemies = 20;
}
public class SpawnEnemy : MonoBehaviour
{
public GameObject[] waypoints;
public GameObject testEnemyPrefab;
public Wave[] waves;
public int timeBetweenWaves = 5;
private GameManagerBehavior gameManager;
private float lastSpawnTime;
private int enemiesSpawned = 0;
// Use this for initialization
void Start()
{
lastSpawnTime = Time.time;
gameManager =
GameObject.Find("GameManager").GetComponent<GameManagerBehavior>();
}
// Update is called once per frame
void Update()
{
// 1 Get the index of the current wave, and check if it’s the last one.
int currentWave = gameManager.Wave;
if (currentWave < waves.Length)
{
// 2 If so, calculate how much time passed since the last enemy spawn and whether it’s time to spawn an enemy. Here you consider two cases.
// If it’s the first enemy in the wave, you check whether timeInterval is bigger than timeBetweenWaves.
// Otherwise, you check whether timeInterval is bigger than this wave’s spawnInterval. In either case, you make sure you haven’t spawned all the enemies for this wave.
float timeInterval = Time.time - lastSpawnTime;
float spawnInterval = waves[currentWave].spawnInterval;
if (((enemiesSpawned == 0 && timeInterval > timeBetweenWaves) ||
timeInterval > spawnInterval) &&
enemiesSpawned < waves[currentWave].maxEnemies)
{
// 3 If necessary, spawn an enemy by instantiating a copy of enemyPrefab. You also increase the enemiesSpawned count.
lastSpawnTime = Time.time;
GameObject newEnemy = (GameObject)
Instantiate(waves[currentWave].enemyPrefab);
newEnemy.GetComponent<MoveEnemy>().waypoints = waypoints;
newEnemy.GetComponent<MoveEnemy>().JiggleWaypoints();
enemiesSpawned++;
}
// 4 You check the number of enemies on screen. If there are none and it was the last enemy in the wave you spawn the next wave.
// You also give the player 10 percent of all gold left at the end of the wave.
if (enemiesSpawned == waves[currentWave].maxEnemies &&
GameObject.FindGameObjectWithTag("Enemy") == null)
{
gameManager.Wave++;
gameManager.Gold = Mathf.RoundToInt(gameManager.Gold * 1.1f);
enemiesSpawned = 0;
lastSpawnTime = Time.time;
}
// 5 Upon beating the last wave this runs the game won animation.
}
else {
gameManager.gameOver = true;
GameObject gameOverText = GameObject.FindGameObjectWithTag("GameWon");
gameOverText.GetComponent<Animator>().SetBool("gameOver", true);
}
}
}
Second Class
using UnityEngine;
using System.Collections;
public class MoveEnemy : MonoBehaviour
{
[System.NonSerialized]
public GameObject[] waypoints;
private int currentWaypoint = 0;
private float lastWaypointSwitchTime;
public float speed = 1.0f;
// Use this for initialization
void Start()
{
lastWaypointSwitchTime = Time.time;
}
// Update is called once per frame
void Update()
{
// 1
Vector3 startPosition = waypoints[currentWaypoint].transform.position;
Vector3 endPosition = waypoints[currentWaypoint + 1].transform.position;
// 2
float pathLength = Vector3.Distance(startPosition, endPosition);
float totalTimeForPath = pathLength / speed;
float currentTimeOnPath = Time.time - lastWaypointSwitchTime;
gameObject.transform.position = Vector3.Lerp(startPosition, endPosition, currentTimeOnPath / totalTimeForPath);
// 3
if (gameObject.transform.position.Equals(endPosition))
{
if (currentWaypoint < waypoints.Length - 2)
{
// 3.a
currentWaypoint++;
lastWaypointSwitchTime = Time.time;
RotateIntoMoveDirection();
}
else {
// 3.b
Destroy(gameObject);
AudioSource audioSource = gameObject.GetComponent<AudioSource>();
AudioSource.PlayClipAtPoint(audioSource.clip, transform.position);
//<< deduct health
GameManagerBehavior gameManager =
GameObject.Find("GameManager").GetComponent<GameManagerBehavior>();
gameManager.Health -= 1;
//>>
}
}
}
public void JiggleWaypoints()
{
for (int i = 1; i < waypoints.Length; i++)
{
waypoints[i].transform.position = new Vector3(waypoints[i].transform.position.x + Random.Range(-3, 3), waypoints[i].transform.position.y + Random.Range(-3, 3), 0);
}
}
private void RotateIntoMoveDirection()
{
//1 It calculates the bug’s current movement direction by subtracting the current waypoint’s position from that of the next waypoint.
Vector3 newStartPosition = waypoints[currentWaypoint].transform.position;
Vector3 newEndPosition = waypoints[currentWaypoint + 1].transform.position;
Vector3 newDirection = (newEndPosition - newStartPosition);
//2 It uses Mathf.Atan2 to determine the angle toward which newDirection points, in radians, assuming zero points to the right.
// Multiplying the result by 180 / Mathf.PI converts the angle to degrees.
float x = newDirection.x;
float y = newDirection.y;
float rotationAngle = Mathf.Atan2(y, x) * 180 / Mathf.PI;
//3 Finally, it retrieves the child named Sprite and rotates it rotationAngle degrees along the z-axis.
// Note that you rotate the child instead of the parent so the health bar — you’ll add it soon — remains horizontal.
GameObject sprite = (GameObject)
gameObject.transform.FindChild("Sprite").gameObject;
sprite.transform.rotation =
Quaternion.AngleAxis(rotationAngle, Vector3.forward);
}
public float distanceToGoal()
{
float distance = 0;
distance += Vector3.Distance(
gameObject.transform.position,
waypoints[currentWaypoint + 1].transform.position);
for (int i = currentWaypoint + 1; i < waypoints.Length - 1; i++)
{
Vector3 startPosition = waypoints[i].transform.position;
Vector3 endPosition = waypoints[i + 1].transform.position;
distance += Vector3.Distance(startPosition, endPosition);
}
return distance;
}
}
Code is working 100% without errors, BUT....
After each spawn all objects get the same waypoint array. This can be seen on the screen as all objects jump to new waypoint in line together each time new object is spawned. I want the object which is already spawn to live life with it's own array of only once created waypoints.
You need to create a new array of waypoints each time you create one from the prefabricated object. You don't show your Instantiate method but I'm guessing that it has a line like this:
this.waypoints = prefab.waypoints;
This will mean that all object you create will share the same list of waypoints (as you've discovered).
What you need is something like this - assuming that the waypoints have X, Y, and Z properties):
this.waypoints = new GameObject[5];
for (int i = 0; i++ ; i < 5)
{
this.waypoints[i].X = prefab.waypoints[i].X;
this.waypoints[i].Y = prefab.waypoints[i].Y;
this.waypoints[i].Z = prefab.waypoints[i].Z;
}
(If you want your points to be a variable length you might want to consider using a list).
This means that each object has a list of unique points even if they start with the same values you can change each independently.
Based on ChrisFs' and Joe Blows' answers, do something like this in your MoveEnemy script:
private Vector3[] myWay;
public void JiggleWaypoints(GameObject[] waypoints)
{
myWay = new Vector3[waypoints.Length];
for(int i = 1; i < waypoints.Length; i++)
{
myWay[i] = new Vector3(waypoints[i].transform.position.x + Random.Range(-3, 4), waypoints[i].transform.position.y + Random.Range(-3, 4), 0);
}
}
myWay replaces the GameObject[].
In your SpawnEnemy script you do this:
GameObject e = (GameObject)Instantiate(enemyPrefab);
e.GetComponent<MoveEnemy>().JiggleWaypoints(waypoints);

Categories