Hello everyone,
I’m looking for guidance on a C# issue.
I’m trying to learn Unity (second day of study) and I’m stuck with a behavior that I don’t understand.
I have a scene with a terrain and 3 actors.
I imported some scripts to apply camera movement RTS-style and I’m trying to follow some youtube tutorials on navigation to move units around, however I saw that in the tutorial the guy reference to tags to see if an object is selectable, is ground or whatever. I don’t think using tags would be a good idea (can forget to add tags, could change tags later down the line, etc.), so I came up with a script to give some generic properties to GameObjects that I will interact with.
I attached the scripts to the terrain (marking it as “not selectable”) and other game objects (“selectable”).
However, I have 2 problems:
- the script instantiate 1 new GameObject each left click on a “new” (not the previously selected) object, and
- if i left click the terrain I got
RTSCameraController.LeftClick () (at Assets/Scripts/RTSCameraController.cs:105)```
here the code:
Camera Controller:
```csharp
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(Camera))]
public class RTSCameraController : MonoBehaviour
{
#region Camera
public float ScreenEdgeBorderThickness = 5.0f; // distance from screen edge. Used for mouse movement
[Header("Camera Mode")]
[Space]
public bool RTSMode = true;
public bool FlyCameraMode = false;
[Header("Movement Speeds")]
[Space]
public float minPanSpeed;
public float maxPanSpeed;
public float secToMaxSpeed; //seconds taken to reach max speed;
public float zoomSpeed;
[Header("Movement Limits")]
[Space]
public bool enableMovementLimits;
public Vector2 heightLimit;
public Vector2 lenghtLimit;
public Vector2 widthLimit;
private Vector2 zoomLimit;
private float panSpeed;
private Vector3 initialPos;
private Vector3 panMovement;
private Vector3 pos;
private Quaternion rot;
private bool rotationActive = false;
private Vector3 lastMousePosition;
private Quaternion initialRot;
private float panIncrease = 0.0f;
[Header("Rotation")]
[Space]
public bool rotationEnabled;
public float rotateSpeed;
#endregion
private GameObject lastSelected;
private GameObject currentSelected;
// Use this for initialization
void Start()
{
initialPos = transform.position;
initialRot = transform.rotation;
zoomLimit.x = 15;
zoomLimit.y = 65;
lastSelected = new GameObject();
currentSelected = new GameObject();
}
void Update()
{
# region Camera Mode
//check that ony one mode is choosen
if (RTSMode == true) FlyCameraMode = false;
if (FlyCameraMode == true) RTSMode = false;
#endregion
Move();
#region Zoom
Camera.main.fieldOfView -= Input.mouseScrollDelta.y * zoomSpeed;
Camera.main.fieldOfView = Mathf.Clamp(Camera.main.fieldOfView, zoomLimit.x, zoomLimit.y);
#endregion
Rotate();
if (Input.GetMouseButtonDown(0))
{
LeftClick();
}
}
public void LeftClick()
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit, 100))
{
currentSelected = hit.collider.gameObject;
if (currentSelected.GetComponent<GenericObjectInfo>() != null)
{
if (currentSelected.name != lastSelected.name)
{
if (!currentSelected.GetComponent<GenericObjectInfo>().IsSelectable())
{
lastSelected.GetComponent<GenericObjectInfo>().SetSelected(false);
lastSelected = new GameObject();
}else if(lastSelected.GetComponent<GenericObjectInfo>() == null)
{
currentSelected.GetComponent<GenericObjectInfo>().SetSelected(true);
lastSelected = currentSelected;
}else
{
lastSelected.GetComponent<GenericObjectInfo>().SetSelected(false);
currentSelected.GetComponent<GenericObjectInfo>().SetSelected(true);
lastSelected = currentSelected;
}
}
}else if (lastSelected.name != null)
{
lastSelected.GetComponent<GenericObjectInfo>().SetSelected(false);
lastSelected = new GameObject();
}
}
}
private void Move()
{
#region Movement
panMovement = Vector3.zero;
if (Input.GetKey(KeyCode.W) || Input.mousePosition.y >= Screen.height - ScreenEdgeBorderThickness)
{
panMovement += Vector3.forward * panSpeed * Time.deltaTime;
}
if (Input.GetKey(KeyCode.S) || Input.mousePosition.y <= ScreenEdgeBorderThickness)
{
panMovement -= Vector3.forward * panSpeed * Time.deltaTime;
}
if (Input.GetKey(KeyCode.A) || Input.mousePosition.x <= ScreenEdgeBorderThickness)
{
panMovement += Vector3.left * panSpeed * Time.deltaTime;
}
if (Input.GetKey(KeyCode.D) || Input.mousePosition.x >= Screen.width - ScreenEdgeBorderThickness)
{
panMovement += Vector3.right * panSpeed * Time.deltaTime;
//pos.x += panSpeed * Time.deltaTime;
}
if (Input.GetKey(KeyCode.Q))
{
panMovement += Vector3.up * panSpeed * Time.deltaTime;
}
if (Input.GetKey(KeyCode.E))
{
panMovement += Vector3.down * panSpeed * Time.deltaTime;
}
if (RTSMode) transform.Translate(panMovement, Space.World);
else if (FlyCameraMode) transform.Translate(panMovement, Space.Self);
//increase pan speed
if (Input.GetKey(KeyCode.W) || Input.GetKey(KeyCode.S)
|| Input.GetKey(KeyCode.A) || Input.GetKey(KeyCode.D)
|| Input.GetKey(KeyCode.E) || Input.GetKey(KeyCode.Q)
|| Input.mousePosition.y >= Screen.height - ScreenEdgeBorderThickness
|| Input.mousePosition.y <= ScreenEdgeBorderThickness
|| Input.mousePosition.x <= ScreenEdgeBorderThickness
|| Input.mousePosition.x >= Screen.width - ScreenEdgeBorderThickness)
{
panIncrease += Time.deltaTime / secToMaxSpeed;
panSpeed = Mathf.Lerp(minPanSpeed, maxPanSpeed, panIncrease);
}
else
{
panIncrease = 0;
panSpeed = minPanSpeed;
}
#endregion
#region boundaries
if (enableMovementLimits == true)
{
//movement limits
pos = transform.position;
pos.y = Mathf.Clamp(pos.y, heightLimit.x, heightLimit.y);
pos.z = Mathf.Clamp(pos.z, lenghtLimit.x, lenghtLimit.y);
pos.x = Mathf.Clamp(pos.x, widthLimit.x, widthLimit.y);
transform.position = pos;
}
#endregion
}
private void Rotate()
{
#region mouse rotation
if (rotationEnabled)
{
// Mouse Rotation
if (Input.GetMouseButton(2))
{
rotationActive = true;
Vector3 mouseDelta;
if (lastMousePosition.x >= 0 &&
lastMousePosition.y >= 0 &&
lastMousePosition.x <= Screen.width &&
lastMousePosition.y <= Screen.height)
mouseDelta = Input.mousePosition - lastMousePosition;
else
{
mouseDelta = Vector3.zero;
}
var rotation = Vector3.up * Time.deltaTime * rotateSpeed * mouseDelta.x;
rotation += Vector3.left * Time.deltaTime * rotateSpeed * mouseDelta.y;
transform.Rotate(rotation, Space.World);
// Make sure z rotation stays locked
rotation = transform.rotation.eulerAngles;
rotation.z = 0;
transform.rotation = Quaternion.Euler(rotation);
}
if (Input.GetMouseButtonUp(0))
{
rotationActive = false;
if (RTSMode) transform.rotation = Quaternion.Slerp(transform.rotation, initialRot, 0.5f * Time.time);
}
lastMousePosition = Input.mousePosition;
}
#endregion
}
}
and the GenericInformation I attach to Objects:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class GenericObjectInfo : MonoBehaviour
{
public bool isSelectable = false;
public bool isSelected = false;
public string objectName;
private NavMeshAgent agent;
public bool isMovable = false;
private Transform currentTarget;
// Start is called before the first frame update
void Start()
{
if (isSelectable)
{
agent = GetComponent<NavMeshAgent>();
}
}
// Update is called once per frame
void Update()
{
if (currentTarget != null)
{
agent.destination = currentTarget.position;
}
if(Input.GetMouseButton(1) && isSelected)
{
MoveUnit();
}
}
public void MoveUnit()
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if(Physics.Raycast(ray, out RaycastHit hit, 100)){
agent.destination = hit.point;
Debug.Log("Moving to"+hit.point);
}
}
public bool IsSelectable ()
{
return isSelectable;
}
public void SetSelectable (bool var)
{
isSelectable = var;
}
public void MoveUnit (Vector3 dest)
{
currentTarget = null;
agent.destination = dest;
}
public bool IsMovable()
{
return isMovable;
}
public void SetMovable(bool var)
{
isMovable = var;
}
public void SetSelected(bool selectionToggle)
{
isSelected = selectionToggle;
Debug.Log("this " + this.name + "has been SetSelected to" + selectionToggle);
}
public void SetNewTarget(Transform enemy)
{
currentTarget = enemy;
}
}