Anti Speed Hack (Unity3d/C#) - c#

I wrote this simple anti speed hack for unity, and in theory and practice it does (somewhat) works. But if the game is being alt+tabbed or minimized, or even sometimes out of nowhere, code thinks time has changed. I'm assuming it has something to do with the time lag? Anyways, here's the script:
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
public class AntiHack : MonoBehaviour {
public static float systemTime = 0F;
public static float timer = 0F;
public static bool kickPlayer = false;
public float tolerance = 1.1f;
int resetTime = 0;
// UI Canvas
public Canvas antihack_Canvas;
void Start()
{
systemTime = System.DateTime.Now.Second;
timer = System.DateTime.Now.Second;
}
void Update()
{
if (systemTime == 10F || systemTime == 50F)
{
timer = System.DateTime.Now.Second;
resetTime = 0;
}
systemTime = System.DateTime.Now.Second;
timer += Time.deltaTime;
float result = timer - systemTime;
if (result < 0 )
{
result = result * -1;
}
if (result > tolerance && kickPlayer == true && systemTime > 10F)
{
KickPlayer();
}
if (result > 60 + tolerance && systemTime < 10F && kickPlayer == true)
{
KickPlayer();
}
}
//If player got caught do this
void KickPlayer()
{
Application.LoadLevel ("antiHackScreen");
}
public static void RestartTimer(bool kick)
{
timer = System.DateTime.Now.Second;
kickPlayer = kick;
}
}
And I'm using this when the level is being started:
public class restartTimer : MonoBehaviour {
// Use this for initialization
void Start () {
AntiHack.RestartTimer (true);
}
}
Any help would be appreciated! Thank you!

Related

How to wait for the canvas fade in out to finish before saving the game?

this script make a canvas group alpha to change between 0 and 1 :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;
public class Description : MonoBehaviour
{
public Canvas canvas;
public AnimationCurve animationCurve;
public float fadingSpeed = 5f;
public TMP_InputField _inputField;
public enum Direction { FadeIn, FadeOut };
private CanvasGroup canvasGroup;
void Start()
{
if (canvas == null) canvas = GetComponent<Canvas>();
canvasGroup = canvas.GetComponent<CanvasGroup>();
if (canvasGroup == null) Debug.LogError("Please assign a canvas group to the canvas!");
if (animationCurve.length == 0)
{
Debug.Log("Animation curve not assigned: Create a default animation curve");
animationCurve = AnimationCurve.EaseInOut(0f, 0f, 1f, 1f);
}
}
public void StartFading(bool InOut)
{
if (canvasGroup != null)
{
if (InOut)
{
StartCoroutine(FadeCanvas(canvasGroup, Direction.FadeIn, fadingSpeed));
}
else
{
StartCoroutine(FadeCanvas(canvasGroup, Direction.FadeOut, fadingSpeed));
}
}
}
public IEnumerator FadeCanvas(CanvasGroup canvasGroup, Direction direction, float duration)
{
var startTime = Time.time;
var endTime = Time.time + duration;
var elapsedTime = 0f;
if (direction == Direction.FadeIn) canvasGroup.alpha = animationCurve.Evaluate(0f);
else canvasGroup.alpha = animationCurve.Evaluate(1f);
while (Time.time <= endTime)
{
elapsedTime = Time.time - startTime;
var percentage = 1 / (duration / elapsedTime);
if ((direction == Direction.FadeOut)) // if we are fading out
{
canvasGroup.alpha = animationCurve.Evaluate(1f - percentage);
}
else
{
canvasGroup.alpha = animationCurve.Evaluate(percentage);
}
yield return new WaitForEndOfFrame();
}
if (direction == Direction.FadeIn) canvasGroup.alpha = animationCurve.Evaluate(1f);
else canvasGroup.alpha = animationCurve.Evaluate(0f);
_inputField.readOnly = false;
}
}
and using it :
using UnityEngine;
using System.Collections;
using System.IO;
public class SavingGame : MonoBehaviour
{
public int resWidth = 1920;
public int resHeight = 1080;
public SaveLoad saveLoad;
public Description description;
private static int countName;
private void Start()
{
countName = 0;
string[] dirs = Directory.GetDirectories(Application.persistentDataPath + "\\" + "Saved Screenshots",
"*.*", SearchOption.TopDirectoryOnly);
if(dirs.Length > 0)
{
countName = dirs.Length;
}
}
public static string ScreenShotName(int width, int height)
{
return string.Format("{0}/Saved Screenshots/SaveSlot{1} SavedGameSlot_{2}x{3}_{4}/SavedGameSlot_{1}x{2}_{3}.png",
Application.persistentDataPath,
countName,
width, height, System.DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss"));
}
void Update()
{
if (Input.GetKeyDown("k"))
{
description.StartFading(true);
}
}
public void Save()
{
description.StartFading(false);
string filename = ScreenShotName(resWidth, resHeight);
string directory = Path.GetDirectoryName(filename);
Directory.CreateDirectory(directory);
ScreenCapture.CaptureScreenshot(filename);
StartCoroutine(saveLoad.SaveWithTime(directory, Path.GetFileNameWithoutExtension(filename) + ".savegame.txt"));
countName++;
}
}
I'm calling the Save method through the editor ui button onclick event.
the problem is before saving i want first the fading out of the canvas to be finished and then making the rest of the saving code in the Save method :
public void Save()
{
description.StartFading(false);
i want that after finished the StartFading then to make the saving :
string filename = ScreenShotName(resWidth, resHeight);
string directory = Path.GetDirectoryName(filename);
Directory.CreateDirectory(directory);
ScreenCapture.CaptureScreenshot(filename);
StartCoroutine(saveLoad.SaveWithTime(directory, Path.GetFileNameWithoutExtension(filename) + ".savegame.txt"));
countName++;
not sure how to do it. using a while maybe in the Save method ?
There are countless ways to solve it actually so the easiest (if you prefer) way to do it would be to check it in update if the canvas alpha is == 0 then call save once by having a boolean lets save "canSave" let me show you an example actually:
private void update() {
if( canvas.alpha == 0 && canSave ) {
Save();
}
}
or you can do it in an efficient way by making a callback for fadeout panel function like:
public IEnumerator FadeCanvas(CanvasGroup canvasGroup, Direction direction, float duration, Action callBack ) {
// your code
// if you want to you can also wait for some seconds over here too
// like yield return new waitForSeconds(2);
// after that just simply write this line of code
callback();
}
So now when you call the fadepanel function you can call it this way:
StartCoroutine( FadeCanvas( blah blah all the parameters and in last, () => {
save();
} ) );
so this will call save function itself when the callback is called inside your FadeCanvas function, there are some other ways to do so too but for now, try one of them.
I hope it helps and I made myself clear, and hopefully, this should work for you.

How to scale only one game object in the AR scene in Unity?

so I have like 5 game object in my scene but I only scale each of them separately. However when I try to do that all of them start scaling simultaneously. Also, I have a placement indicator that would be used to instantiate the object on the plane. It seems that instead of the object itself, the placement indicator is the one that gets scaled. How should I fix that?
I have tried deactivating the placement indicator but did not work.
Here is the code for instantiating objects:
I limited the obj number to 5.
I use this script instead of the usual "PlaceonPlane" script.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.XR.ARFoundation;
using UnityEngine.Experimental.XR;
using UnityEngine.UI;
using UnityEngine.XR.ARSubsystems;
public class ARTaptoPlaceObject : MonoBehaviour
{
private ARSessionOrigin arOrigin;
GameObject spawnedobj;
public GameObject placementIndicator;
private ARRaycastManager arRaycast;
public Pose placementPose;
public UIContoller sc;
public bool placementPoseIsValid = false;
private int count;
private string valu;
string prefabs;
void Start()
{
arOrigin = FindObjectOfType<ARSessionOrigin>();
arRaycast = FindObjectOfType<ARRaycastManager>();
count = 0;
}
// Update is called once per frame
void Update()
{
UpdatePlacementPose();
UpdatePlacementIndicator();
for (var i = 0; i < Input.touchCount; ++i)
{
if (Input.GetTouch(i).phase == TouchPhase.Began)
{
if (placementPoseIsValid && Input.GetTouch(i).tapCount == 2)
{
PlaceObject();
}
}
}
}
public void PlaceObject()
{
if (count <= 4)
{
if (sc.objectToPlace != null)
{
spawnedobj = Instantiate(sc.objectToPlace, placementPose.position, placementPose.rotation);
arOrigin.MakeContentAppearAt(spawnedobj.transform, spawnedobj.transform.position, spawnedobj.transform.rotation);
count++;
}
}
else
{
placementIndicator.SetActive(false);
}
}
private void UpdatePlacementIndicator()
{
if (placementPoseIsValid && count <= 4 && sc.active == false)
{
placementIndicator.SetActive(true);
placementIndicator.transform.SetPositionAndRotation(placementPose.position, placementPose.rotation);
}
else
{
placementIndicator.SetActive(false);
}
}
private void UpdatePlacementPose()
{
var screenCenter = Camera.current.ViewportToScreenPoint(new Vector3(0.5f, 0.5f));
var hits = new List<ARRaycastHit>();
arRaycast.Raycast(screenCenter, hits, UnityEngine.XR.ARSubsystems.TrackableType.Planes);
placementPoseIsValid = hits.Count > 0;
if (placementPoseIsValid)
{
placementPose = hits[0].pose;
var cameraForward = Camera.current.transform.forward;
var cameraBearing = new Vector3(cameraForward.x, 0, cameraForward.z).normalized;
placementPose.rotation = Quaternion.LookRotation(cameraBearing);
}
}
}
and here is the Scaler script that's attached to the button that would scale the object.
public class Scaler : MonoBehaviour
{
public UIContoller uc;
public ARTaptoPlaceObject ap;
private GameObject ReferenceToScale;
public void OnValueChange()
{
ReferenceToScale = (UnityEngine.GameObject)Resources.Load(uc.s_count, typeof(GameObject));
Vector3 t = ReferenceToScale.transform.localScale;
Vector3 scaleValue = t * 1.1f;
ReferenceToScale.transform.localScale = scaleValue;
}
Also the "objectToPlace" itself is in the "UI.Controller" script as I could not view it in the scene when it was in the "ARTaptoPlace" script

How can I start conversation only if the object has finished scaling up?

The scaling script :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Scaling : UnityEngine.MonoBehaviour
{
public GameObject objectToScale;
public GameObject lookAtTarget;
public float duration = 1f;
public Vector3 minSize;
public Vector3 maxSize;
public bool scaleUp = false;
public Coroutine scaleCoroutine;
[HideInInspector]
public bool scaledFinishedUp = false;
[HideInInspector]
public bool scaledFinishedDown = false;
public void Inits()
{
objectToScale.transform.localScale = minSize;
}
public IEnumerator scaleOverTime(GameObject targetObj, Vector3 toScale, float duration, Camera objectToScaleCamera)
{
float counter = 0;
Vector3 startScaleSize = targetObj.transform.localScale;
while (counter < duration)
{
counter += Time.deltaTime;
targetObj.transform.localScale = Vector3.Lerp(startScaleSize, toScale, counter / duration);
if (scaleUp)
{
var lookPos = lookAtTarget.transform.position - objectToScale.transform.position;
lookPos.y = 0;
var rotation = Quaternion.LookRotation(lookPos);
objectToScale.transform.rotation = Quaternion.Slerp(objectToScale.transform.rotation, rotation, counter / duration);
}
else
{
var lookPos = lookAtTarget.transform.position - objectToScale.transform.position;
lookPos.y = 0;
var rotation = Quaternion.LookRotation(objectToScaleCamera.transform.forward);//SwitchCameras.GetCurrentCamera().transform.forward);//Camera.main.transform.forward);
objectToScale.transform.rotation = Quaternion.Slerp(objectToScale.transform.rotation, rotation, counter / duration);
}
yield return null;
}
if(objectToScale.transform.localScale.x >= maxSize.x
&& objectToScale.transform.localScale.y >= maxSize.y
&& objectToScale.transform.localScale.z >= maxSize.z)
{
scaledFinishedUp = true;
}
if (objectToScale.transform.localScale.x <= maxSize.x
&& objectToScale.transform.localScale.y <= maxSize.y
&& objectToScale.transform.localScale.z <= maxSize.z)
{
scaledFinishedDown = true;
}
}
public IEnumerator scaleOverTime(GameObject targetObj, Vector3 toScale, float duration, float rotationSpeed)
{
float counter = 0;
Vector3 startScaleSize = targetObj.transform.localScale;
while (counter < duration)
{
counter += Time.deltaTime;
targetObj.transform.localScale = Vector3.Lerp(startScaleSize, toScale, counter / duration);
targetObj.transform.Rotate(Vector3.up * rotationSpeed * Time.deltaTime, Space.Self);
yield return null;
}
}
}
And the script with the conversations :
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class NaviDialogue : MonoBehaviour
{
public ObjectsManipulation op;
public bool scale = true;
public Scaling scaling;
public ConversationTrigger conversationTrigger;
private void Start()
{
op.canScale = false;
}
private void Update()
{
if (scaling == true && DOFControl.hasFinished == true)
{
DOFControl.hasFinished = false;
PlayerController.disablePlayerController = true;
NaviConversations(0);
}
}
public void NaviConversations(int Index)
{
scaling.scaleUp = true;
op.Scaling(false);
StartCoroutine(conversationTrigger.PlayConversation(Index));
}
}
Just after the line :
op.Scaling(false);
I want to check if the object has finished scaling up then start the StartCoroutine. The problem is that in the Update I'm calling NaviConversations only once.
And then when the StartCoroutine has finished I want to do something else like this : This will scale down back the object :
scaling.scaleUp = false;
op.Scaling(false);
And last the class with the PlayConversatio method :
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEditor;
using UnityEngine;
public class ConversationTrigger : MonoBehaviour
{
public List<Conversation> conversations = new List<Conversation>();
public GameObject canvas;
[HideInInspector]
public static int conversationIndex;
public bool conversationEnd = false;
private bool activateButton = false;
private DialogueManager dialoguemanager;
private bool startDialogue = false;
private void Start()
{
conversationIndex = 0;
dialoguemanager = FindObjectOfType<DialogueManager>();
}
public IEnumerator PlayConversation(int index)
{
if (conversations.Count > 0 &&
conversations[index].Dialogues.Count > 0)
{
for (int i = 0; i < conversations[index].Dialogues.Count; i++)
{
if (dialoguemanager != null)
{
dialoguemanager.StartDialogue(conversations[index].Dialogues[i]);
}
while (DialogueManager.dialogueEnded == false)
{
yield return null;
}
}
conversationIndex = index;
conversationEnd = true;
canvas.SetActive(false);
Debug.Log("Conversation Ended");
}
}
public void SaveConversations()
{
string jsonTransform = JsonHelper.ToJson(conversations.ToArray(), true);
File.WriteAllText(#"d:\json.txt", jsonTransform);
}
public void LoadConversations()
{
string jsonTransform = File.ReadAllText(#"d:\json.txt");
conversations.Clear();
conversations.AddRange(JsonHelper.FromJson<Conversation>(jsonTransform));
}
}
I don't see what happens in
conversationTrigger.PlayConversation(Index) but you could use WaitUntil to the top of it in order to make it wait until the scaling ends.
Something like
yield return new WaitUntil(scalingIsDoneCondition);
where scalingIsDoneCondition is the check whether the scaling has finished. As soon as it returns true the Coroutine continues.
Alternatively you can have an additional IEnumerator and wait there like e.g.
public void NaviConversations(int Index)
{
scaling.scaleUp = true;
op.Scaling(false);
StartCoroutine(StartConversationAfterScaling(Index));
}
private IEnumerator StartConversationAfterScaling(int index)
{
yield return new WaitUntil(scalingIsDoneCondition);
StartCoroutine(conversationTrigger.PlayConversation(Index));
}
If you needed to check the condition from within the same class.
Another form is making the whole scaling rather a public IEnumerator and yield it from the other one
public void NaviConversations(int Index)
{
scaling.scaleUp = true;
StartCoroutine(StartConversationAfterScaling(Index));
}
private IEnumerator StartConversationAfterScaling(int index)
{
yield return op.Scaling(false);
StartCoroutine(conversationTrigger.PlayConversation(Index));
}
this would require to make op.Scaling also an IEnumerator.
I didn't even read the whole of your scripts. Highly recommend you to use a tweening library for such stuff. You can easily scale, rotate, translate, blend colours and many more with these libraries.
Take a look at DoTween, with DoTween you can write scaling like this:
transform.DoScale(Vector3.one * 2, 1f).onCompelete( ()=>
{
print("Scaling finished!");
}
But tweening is not all about setting callbacks, with tween you can animate your object programmatically.
You can check a quick tutorial about capabilities:
YouTube Video

Coroutine couldn't be started because the the game object is inactive

I'm getting an error of "Coroutine couldn't be started because the the game object 'TimeOutWarningDialog' is inactive!" but I'm unsure why I'm getting this error.
Just to give a rundown of the code:
I'm looking for inactivity in GameManger.Update()
If inactive for a period of time I call GameManager.ShowRestartWarning()
TimeOutWarningDialog gets SetActive to true
I check if the object is active before calling StartRestartTimer(), if (timerInstance.activeSelf == true) StartRestartTimer();
I call startTimer() in CountdownTimer class
I'm setting the object that I'm instatiating to 'active' before I call the startTimer function which includes the coroutine. what am I doing wrong here?
any help would be great!!
using UnityEngine;
using System.Collections.Generic;
using UnityEngine.SceneManagement;
public class GameManager : MonoBehaviour
{
// Create Singleton
public static GameManager instance = null;
// Set Default Background Color
public Color defaultColor;
// Restart variables
private Vector3 prevMousePosition;
public GameObject timeOutWarningDialog;
public GameObject restartDialog;
public float countdownLength;
public float timeUntilCountdown;
// Game Controller
private GameObject canvas;
private GameObject gameManager;
public GameObject timerInstance;
public Object startingScene;
private Scene currentScene;
// File System List of Folders
public List<string> folders;
void Awake()
{
if (instance == null)
instance = this;
else if (instance != null)
Destroy(gameObject);
DontDestroyOnLoad(gameObject);
gameManager = GameObject.FindGameObjectWithTag("GameManager");
}
void Start()
{
prevMousePosition = Input.mousePosition;
currentScene = SceneManager.GetActiveScene();
}
void Update()
{
if(Input.anyKeyDown || Input.mousePosition != prevMousePosition)
if(currentScene.name != startingScene.name)
StartGameTimer();
prevMousePosition = Input.mousePosition;
}
// GAME TIMER
void StartGameTimer()
{
// Debug.Log("Game Timer Started");
CancelInvoke();
if (GameObject.FindGameObjectWithTag("Timer") == null)
Invoke("ShowRestartWarning", timeUntilCountdown);
}
void ShowRestartWarning()
{
canvas = GameObject.FindGameObjectWithTag("Canvas");
timerInstance = Instantiate(timeOutWarningDialog);
timerInstance.transform.SetParent(canvas.transform, false);
timerInstance.SetActive(true);
if (timerInstance.activeSelf == true)
StartRestartTimer();
}
void StartRestartTimer()
{
CountdownTimer countdownTimer = timeOutWarningDialog.GetComponent<CountdownTimer>();
countdownTimer.startTimer(countdownLength);
CancelInvoke();
Invoke("RestartGame", countdownLength);
}
void RestartGame()
{
SceneManager.LoadScene(startingScene.name);
Debug.Log("Game Restarted");
Debug.Log("Current Scene is " + currentScene.name + ".");
}
void DestroyTimer()
{
Destroy(GameObject.FindGameObjectWithTag("Timer"));
}
}
then I'm calling startTimer in the CountdownTimer class below:
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
public class CountdownTimer : MonoBehaviour
{
public float countdownLength;
public Text timerText;
public bool stop = true;
private float minutes;
private float seconds;
public void startTimer(float from)
{
stop = false;
countdownLength = from;
Update();
StartCoroutine(updateCoroutine());
}
void Update()
{
if (stop) return;
countdownLength -= Time.deltaTime;
minutes = Mathf.Floor(countdownLength / 60);
seconds = countdownLength % 60;
if (seconds > 59) seconds = 59;
if (minutes < 0)
{
stop = true;
minutes = 0;
seconds = 0;
}
}
private IEnumerator updateCoroutine()
{
while (!stop)
{
timerText.text = string.Format("{0:0}:{1:00}", minutes, seconds);
yield return new WaitForSeconds(0.2f);
Debug.Log(string.Format("{0:0}:{1:00}", minutes, seconds));
}
}
}
The problem is in this method:
void StartRestartTimer()
{
CountdownTimer countdownTimer = timeOutWarningDialog.GetComponent<CountdownTimer>();
countdownTimer.startTimer(countdownLength);
CancelInvoke();
Invoke("RestartGame", countdownLength);
}
You start the coroutine first and then invoke RestartGame to load another scene. So the object with the coroutine gets destroyed.
I can't give you the solution because it requires more knowledge regarding your scenes but you may want to try additive scene loading.

Attack timer stops after killing enemy (when attack script loose target) (Unity)

Hey guys! I have a problem, I have attack script with cooldown and stuff in it, I've created basic combat system, everything works until I kill enemy, it destroys it as intended but then my attack timer stops counting until I select another enemy. Also I keep getting an error until I select first enemy because target field in attack script is empty at start.
Scripts:
Attack Script:
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
public class BasicAttack : MonoBehaviour {
public GameObject target; //target to attack
public int damage;
public float range = 4;
public float attackTimer;
public float cooldown = 2.0f;
public GameObject damageNumber;
public GameObject cooldownImage;
public Text cooldownText;
Targeting t;
UserInterface UI;
void Start () {
cooldownImage.SetActive(false);
attackTimer = 0;
t = FindObjectOfType<Targeting>();
UI = FindObjectOfType<UserInterface>();
}
void Update () {
float distance = Vector3.Distance(target.transform.position, transform.position); //calculating distance
cooldownText.text = attackTimer.ToString("F0");
if (attackTimer > 0) {
attackTimer -= Time.deltaTime;
}
if (attackTimer <= 0) {
attackTimer = 0;
}
if (Input.GetKeyUp("1")) { //attack key
if (attackTimer == 0 && distance < range) {
Attack();
attackTimer = cooldown;
//damage numbers
var clone = (GameObject)Instantiate(damageNumber, t.selectedTarget.GetComponent<EnemyAI>().hitPoint.position, t.myTransform.rotation);
clone.GetComponent<DamageNumbers>().damageNumber = damage;
}
else {
Debug.Log("Target is out of range!");
}
}
else {
cooldownImage.SetActive(true);
}
if (attackTimer == 0) {
cooldownImage.SetActive(false);
}
}
public void Attack() {
float distance = Vector3.Distance(target.transform.position, transform.position); //calculating distance
Vector3 dir = (target.transform.position - transform.position).normalized; //calculating direction
float direction = Vector3.Dot(dir, transform.forward); //calculating direction
if (distance < range) { //making player not be able to attack if too far
if (direction > 0) { //making player not be able to attack if target not in front of him
EnemyHealth eh = (EnemyHealth)target.GetComponent("EnemyHealth"); //getting enemy health
t.selectedTarget.GetComponent<EnemyHealth>().TakeDamage(-damage); //adjusting enemy health
UI.infoText.text = "";
}
else {
Debug.Log("Target needs to be in front of you!");
}
UI.infoText.text = "";
}
else {
Debug.Log("Target is out of range!");
}
} //attack
}
EnemyHealth Script:
using UnityEngine;
using System.Collections;
public class EnemyHealth : MonoBehaviour {
public float maxHealth = 100;
public float curHealth = 100;
CombatTargetUI ct;
void Start () {
ct = FindObjectOfType<CombatTargetUI>();
}
void Update () {
TakeDamage(0);
}
public void TakeDamage (int ad) {
curHealth += ad;
if (curHealth <= 0) {
curHealth = 0;
/*ct.HideUI();*/
Die();
}
if (curHealth >= maxHealth) {
curHealth = maxHealth;
}
if (maxHealth <= 1) {
maxHealth = 1;
}
}
void Die () {
StartCoroutine(TimeToDestroy());
}
IEnumerator TimeToDestroy () {
yield return new WaitForSeconds(0.5f);
ct.HideUI();
Destroy(gameObject);
}
}
Targeting Script:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class Targeting : MonoBehaviour {
public List<Transform> targets;
public Transform selectedTarget;
public Transform myTransform;
CombatTargetUI ct;
void Start () {
targets = new List<Transform>();
selectedTarget = null;
myTransform = transform;
ct = FindObjectOfType<CombatTargetUI>();
AddAllEnemies();
}
public void AddAllEnemies () {
GameObject[] go = GameObject.FindGameObjectsWithTag("Enemy");
foreach (GameObject enemy in go) {
AddTarget(enemy.transform);
}
}
public void AddTarget (Transform enemy) {
targets.Add(enemy);
}
void SortTargetsByDistance () {
targets.RemoveAll(target => target == null);
targets.Sort(delegate(Transform t1, Transform t2) {
return Vector3.Distance(t1.position, myTransform.position).CompareTo(Vector3.Distance(t2.position, myTransform.position));
});
}
void TargetEnemy () {
if (selectedTarget == null) {
SortTargetsByDistance();
selectedTarget = targets[0];
}
else {
int index = targets.IndexOf(selectedTarget);
if (index < targets.Count - 1) {
index++;
}
else {
index = 0;
}
DeselectTarget();
selectedTarget = targets[index];
}
SelectTarget();
}
void SelectTarget () {
ct.ShowUI();
selectedTarget.GetComponent<Renderer>().material.color = Color.red;
BasicAttack ba = (BasicAttack)GetComponent("BasicAttack");
ba.target = selectedTarget.gameObject;
}
public void DeselectTarget () {
if (selectedTarget != null) {
selectedTarget.GetComponent<Renderer>().material.color = Color.white;
}
selectedTarget = null;
}
void Update () {
if (Input.GetKeyDown(KeyCode.Tab)) {
TargetEnemy();
}
}
}
I think that those are all scripts that might cause problem, can anyone help me? I'm desperate. :(
In beginning of Update method of your Attack Script, add a null check for target object like this:
if(target == null)
{
return;
}
I think I know what your Timer problems are.
If I have understood correctly, in the Basic Attack class - Start Method, you iniate the timer.
Then, the timer goes down until its 0, and then you can attack.
I think the problem its that, once you have destroyed your enemy, nothing else happens.
I mean, you actually don´t reset the timer once the enemy is dead. That´s why it only works again, when you select another enemy.
When that happens, the BasicAttack class is called from the Targeting class, and thus, the Start method is called again.
I hope it helped.
Regards!

Categories