Full Input Handling class (Description below):
using UnityEngine;
using UnityEngine.Networking;
using System.Collections;
using System.Collections.Generic;
namespace Tutorial {
public class TutorialInputManager : MonoBehaviour {
public List<GameObject> selectedObjects;
public List<GameObject> boxSelectedObjects;
public bool selectionTutorialFlag;
public bool attackOrderTutorialFlag;
public bool moveOrderTutorialFlag;
public bool splitTutorialFlag;
public bool mergeTutorialFlag;
public bool attackStandingByFlag;
public GameObject tutorialUnitPrefab;
public TutorialAttackManager attackManager;
public TutorialSplitManager splitManager;
public TutorialMergeManager mergeManager;
//----------------------------------
void Start() {
this.selectedObjects = new List<GameObject>();
TutorialUnitManager.Instance.allObjects = new List<GameObject>();
this.boxSelectedObjects = new List<GameObject>();
//this.selectionTutorialFlag = this.attackOrderTutorialFlag = this.moveOrderTutorialFlag = this.splitTutorialFlag = this.mergeTutorialFlag = true;
if (this.attackManager == null) {
Debug.LogError("Cannot find attack manager for the tutorial.");
}
if (this.splitManager == null) {
Debug.LogError("Cannot find split manager for the tutorial.");
}
GameObject[] existingObjects = GameObject.FindGameObjectsWithTag("Tutorial_Unit");
foreach (GameObject obj in existingObjects) {
TutorialUnitManager.Instance.allObjects.Add(obj);
}
}
void Update() {
SelectOrder();
MoveOrder();
AttackOrder();
SplitOrder();
MergeOrder();
UpdateStatus();
}
//----------------------------------
private void UpdateStatus() {
if (this.selectedObjects.Count > 0 || this.boxSelectedObjects.Count > 0) {
if (this.attackStandingByFlag) {
foreach (GameObject obj in TutorialUnitManager.Instance.allObjects) {
if (this.selectedObjects.Contains(obj)) {
TutorialUnit unit = obj.GetComponent<TutorialUnit>();
if (!unit.isEnemy) {
unit.SetAttackStandby();
}
}
}
}
else {
foreach (GameObject obj in TutorialUnitManager.Instance.allObjects) {
if (obj == null) {
TutorialUnitManager.Instance.removeList.Add(obj);
continue;
}
if (this.selectedObjects.Contains(obj) || this.boxSelectedObjects.Contains(obj)) {
TutorialUnit unit = obj.GetComponent<TutorialUnit>();
if (unit == null) {
TutorialUnitManager.Instance.removeList.Add(obj);
continue;
}
if (!unit.isEnemy) {
if (unit.isStandingBy) {
unit.SetAttackStandby();
}
if (unit.isAttacking) {
unit.SetAttack();
}
if (unit.isSplitting) {
unit.SetDeselect();
unit.SetAttackCancel();
}
if (unit.isSelected) {
unit.SetSelect();
}
}
}
}
}
}
else {
foreach (GameObject obj in TutorialUnitManager.Instance.allObjects) {
if (obj == null) {
TutorialUnitManager.Instance.removeList.Add(obj);
continue;
}
TutorialUnit unit = obj.GetComponent<TutorialUnit>();
unit.SetDeselect();
}
}
}
//----------------------------------
private void SelectOrder() {
if (!this.selectionTutorialFlag) {
return;
}
if (this.attackStandingByFlag) {
return;
}
if (Input.GetMouseButtonDown(0)) {
if (this.selectedObjects.Count > 0) {
foreach (GameObject obj in this.selectedObjects) {
TutorialUnit unit = obj.GetComponent<TutorialUnit>();
unit.SetDeselect();
}
this.selectedObjects.Clear();
}
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit[] hits = Physics.RaycastAll(ray);
bool hasHitUnit = false;
foreach (RaycastHit hit in hits) {
GameObject obj = hit.collider.gameObject;
if (obj.tag.Equals("Tutorial_Unit")) {
hasHitUnit = true;
if (!this.selectedObjects.Contains(obj)) {
TutorialUnit unit = obj.GetComponent<TutorialUnit>();
unit.SetSelect();
this.selectedObjects.Add(obj);
}
break;
}
}
if (!hasHitUnit) {
this.selectedObjects.Clear();
}
}
if (Input.GetMouseButton(0)) {
foreach (GameObject obj in TutorialUnitManager.Instance.allObjects) {
if (obj == null) {
TutorialUnitManager.Instance.removeList.Add(obj);
continue;
}
Vector2 screenPoint = Camera.main.WorldToScreenPoint(obj.transform.position);
screenPoint.y = Screen.height - screenPoint.y;
if (Selection.selectionArea.Contains(screenPoint) && !this.boxSelectedObjects.Contains(obj)) {
this.boxSelectedObjects.Add(obj);
if (!this.selectedObjects.Contains(obj)) {
this.selectedObjects.Add(obj);
}
TutorialUnit unit = obj.GetComponent<TutorialUnit>();
unit.SetSelect();
}
else if (!Selection.selectionArea.Contains(screenPoint) && this.boxSelectedObjects.Contains(obj)) {
this.boxSelectedObjects.Remove(obj);
if (this.selectedObjects.Contains(obj)) {
this.selectedObjects.Remove(obj);
}
TutorialUnit unit = obj.GetComponent<TutorialUnit>();
unit.SetDeselect();
}
}
}
if (Input.GetMouseButtonUp(0)) {
if (this.boxSelectedObjects.Count > 0) {
foreach (GameObject obj in this.boxSelectedObjects) {
if (!this.selectedObjects.Contains(obj)) {
TutorialUnit unit = obj.GetComponent<TutorialUnit>();
unit.SetSelect();
this.selectedObjects.Add(obj);
}
}
this.boxSelectedObjects.Clear();
}
}
}
//----------------------------------
private void AttackOrder() {
if (!this.attackOrderTutorialFlag) {
return;
}
if (Input.GetKeyDown(KeyCode.A)) {
if (!this.attackStandingByFlag) {
if (this.selectedObjects.Count > 0) {
this.attackStandingByFlag = true;
foreach (GameObject obj in this.selectedObjects) {
TutorialUnit unit = obj.GetComponent<TutorialUnit>();
if (!unit.isEnemy) {
unit.SetAttackStandby();
}
}
//this.selectedObjects.Clear();
}
}
}
if (this.attackStandingByFlag) {
if (Input.GetMouseButtonDown(0)) {
this.attackStandingByFlag = false;
foreach (GameObject obj in this.selectedObjects) {
TutorialUnit unit = obj.GetComponent<TutorialUnit>();
unit.SetAttackCancel();
}
this.selectedObjects.Clear();
}
else if (Input.GetMouseButtonDown(1)) {
this.attackStandingByFlag = false;
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit[] hits = Physics.RaycastAll(ray);
//bool hasOrderedAttackTarget = false;
foreach (RaycastHit hit in hits) {
GameObject obj = hit.collider.gameObject;
if (obj.name.Equals("Floor")) {
foreach (GameObject selected in this.selectedObjects) {
TutorialUnit unit = selected.GetComponent<TutorialUnit>();
if (!unit.isEnemy) {
unit.SetAttackCancel();
unit.SetNewDestination(hit.point);
unit.SetAttack();
}
}
//hasOrderedAttackTarget = true;
break;
}
}
//if (hasOrderedAttackTarget) {
// this.selectedObjects.Clear();
//}
}
}
}
//----------------------------------
private void MoveOrder() {
if (!this.moveOrderTutorialFlag) {
return;
}
if (!this.attackStandingByFlag) {
if (Input.GetMouseButtonDown(1)) {
if (this.selectedObjects.Count > 0) {
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit[] hits = Physics.RaycastAll(ray);
foreach (RaycastHit hit in hits) {
GameObject obj = hit.collider.gameObject;
if (obj.name.Equals("Floor")) {
foreach (GameObject select in this.selectedObjects) {
TutorialUnit unit = select.GetComponent<TutorialUnit>();
if (!unit.isEnemy) {
unit.SetAttackCancel();
unit.SetNoEnemyTarget();
unit.enemies.Clear();
unit.SetStartMoving();
unit.SetNewDestination(hit.point);
}
}
break;
}
}
}
//this.selectedObjects.Clear();
}
}
}
//----------------------------------
private void SplitOrder() {
if (!this.splitTutorialFlag) {
return;
}
if (Input.GetKeyDown(KeyCode.S)) {
if (this.selectedObjects.Count > 0) {
bool enemyCheck = false;
foreach (GameObject obj in this.selectedObjects) {
TutorialUnit unit = obj.GetComponent<TutorialUnit>();
if (unit.isEnemy) {
enemyCheck = true;
}
}
if (!enemyCheck) {
foreach (GameObject owner in this.selectedObjects) {
TutorialUnit unit = owner.GetComponent<TutorialUnit>();
GameObject duplicate = GameObject.Instantiate<GameObject>(this.tutorialUnitPrefab);
duplicate.transform.position = owner.transform.position;
unit.SetDeselect();
unit.DisableSelection();
unit.SetSplitting();
unit = duplicate.GetComponent<TutorialUnit>();
unit.SetDeselect();
unit.DisableSelection();
unit.SetSplitting();
unit.initialColor = Color.white;
TutorialUnitManager.Instance.allObjects.Add(duplicate);
this.splitManager.splitGroups.Add(new SplitGroup(owner, duplicate));
}
}
this.selectedObjects.Clear();
}
}
}
//----------------------------------
private void MergeOrder() {
if (!this.mergeTutorialFlag) {
return;
}
if (Input.GetKeyDown(KeyCode.D)) {
if (this.selectedObjects.Count > 0) {
bool enemyCheck = false;
foreach (GameObject obj in this.selectedObjects) {
TutorialUnit unit = obj.GetComponent<TutorialUnit>();
if (unit.isEnemy) {
enemyCheck = true;
}
}
if (!enemyCheck) {
for (int i = 0; i < this.selectedObjects.Count && (i + 1 < this.selectedObjects.Count); i += 2) {
TutorialUnit unit = this.selectedObjects[i].GetComponent<TutorialUnit>();
unit.SetDeselect();
unit.DisableSelection();
unit.SetMerging();
unit = this.selectedObjects[i + 1].GetComponent<TutorialUnit>();
unit.SetDeselect();
unit.DisableSelection();
unit.SetMerging();
this.mergeManager.mergeGroups.Add(new MergeGroup(this.selectedObjects[i], this.selectedObjects[i + 1]));
}
}
this.selectedObjects.Clear();
}
}
}
}
}
And this is the dialog handling code for an interactive RTS tutorial.
using UnityEngine;
using UnityEngine.UI;
using System;
using System.Collections;
using System.Collections.Generic;
namespace Tutorial {
[Serializable]
public struct DialogArrow {
public Vector2 position;
public float angle;
public DialogArrow(float x, float y, float angle) {
this.position = new Vector2(x, y);
this.angle = angle;
}
}
[Serializable]
public struct DialogText {
public Vector2 position;
public string message;
public DialogText(float x, float y, string message) {
this.position = new Vector2(x, y);
this.message = message;
}
}
[Serializable]
public struct DialogProperty {
public DialogText dialogText;
public DialogArrow dialogArrow;
public bool changePosition;
public bool showArrow;
public float elapsedTime;
public DialogProperty(DialogText text, DialogArrow arrow, bool shouldChangePositionOnNextDialog, bool showArrowOnNextDialog, float time) {
this.dialogText = text;
this.dialogArrow = arrow;
this.changePosition = shouldChangePositionOnNextDialog;
this.showArrow = showArrowOnNextDialog;
this.elapsedTime = time;
}
}
public class TutorialDialog : MonoBehaviour {
public RectTransform dialogTransform;
public RectTransform arrowTransform;
public GameObject mainDialog;
public GameObject arrow;
public List<DialogProperty> properties;
public int propertyIterator;
public bool runCoroutine;
void Start() {
if (this.mainDialog == null) {
Debug.LogError("Dialog: Something is wrong.");
}
if (this.arrow == null) {
Debug.LogError("Arrow: Something is wrong.");
}
this.dialogTransform = this.mainDialog.GetComponent<RectTransform>();
this.arrowTransform = this.arrow.GetComponent<RectTransform>();
this.properties = new List<DialogProperty>();
this.runCoroutine = false;
Initialize();
}
void OnGUI() {
if (this.propertyIterator < this.properties.Count) {
DialogProperty property = this.properties[this.propertyIterator];
Text text = this.mainDialog.GetComponentInChildren<Text>();
if (text != null) {
text.text = property.dialogText.message;
}
if (property.changePosition) {
if (this.dialogTransform != null) {
this.dialogTransform.anchoredPosition = property.dialogText.position;
}
}
if (property.showArrow) {
this.arrowTransform.anchoredPosition = property.dialogArrow.position;
this.arrowTransform.localRotation = Quaternion.Euler(0f, 0f, property.dialogArrow.angle);
}
else {
this.arrowTransform.anchoredPosition = new Vector2(0f, 260f);
}
}
}
void Update() {
if (this.runCoroutine) {
this.StartCoroutine(CR_DialogSwitch());
}
}
private IEnumerator CR_DialogSwitch() {
DialogProperty property = this.properties[this.propertyIterator];
if (property.elapsedTime > 0f) {
if (this.mainDialog.activeSelf) {
this.mainDialog.SetActive(false);
}
if (this.arrow.activeSelf) {
this.arrow.SetActive(false);
}
this.properties[this.propertyIterator] = property;
yield return new WaitForSeconds(property.elapsedTime);
}
if (!this.mainDialog.activeSelf) {
this.mainDialog.SetActive(true);
}
if (!this.arrow.activeSelf) {
this.arrow.SetActive(true);
}
this.runCoroutine = false;
}
public void OnTutorialButtonClick() {
this.propertyIterator++;
if (this.propertyIterator < this.properties.Count) {
this.runCoroutine = true;
}
switch (this.propertyIterator) {
default:
break;
case 6:
case 9:
case 11:
case 15:
TutorialManager.Instance.IncrementState();
break;
}
}
}
}
Typing this in Xenforo forum text editor is slow as hell. Spell check for the win.
As you can see, in the Input Manager, I poll the Inputs to check and see if the user has pressed keys or mouse buttons in the Update() function. In the Dialog class, I only activate the OnTutorialButtonClick() when the user presses a button. Since InputManager polls for hardware key changes, while the EventSystem checks for UI updates, I would to find a way to have EventSystem block polling after it detects an UI update.
That is where GraphicsRaycaster comes in. I might be able to obtain the mouse button click event, and check to see if it’s the UI or the input polling, and turn off the input polling first before UI updates happen.
Just trying to use GameObject.Find(“EventSystem”).GetComponent() doesn’t give much, since it returns null.
Oh yeah, I only use OnGUI() for the fact that it updates every other frames (not Update() or FixedUpdate(), and that it runs only when the user does something (key press, move cursor, etc.), which is what I wanted). It has nothing to do with Legacy UI.