Unity HTC VIVE Teleportation - c#

I am developing for the HTC VIVE and am trying to create a teleportation script that would allow the user to teleport to a certain location (predefined by me) when the user grabs a certain object. I currently have a teleportation code that works like a normal teleporter where the user points at a location and the room is moved to that location. I have modified this so that no matter where the user is pointing they will always teleport to the specific location. This is a first step but I am really looking to trigger this teleportation when the user picks up a certain object, does anyone have any ideas on where to star or how to do this?
Here is the code for the modified teleporter:
namespace VRTK{
using UnityEngine;
using System.Collections;
public delegate void TeleportEventHandler(object sender, DestinationMarkerEventArgs e);
public class VRTK_BasicTeleport : MonoBehaviour
{
public float blinkTransitionSpeed = 0.6f;
[Range(0f, 32f)]
public float distanceBlinkDelay = 0f;
public bool headsetPositionCompensation = true;
public string ignoreTargetWithTagOrClass;
public bool limitToNavMesh = false;
public event TeleportEventHandler Teleporting;
public event TeleportEventHandler Teleported;
protected Transform eyeCamera;
protected bool adjustYForTerrain = false;
protected bool enableTeleport = true;
private float blinkPause = 0f;
private float fadeInTime = 0f;
private float maxBlinkTransitionSpeed = 1.5f;
private float maxBlinkDistance = 33f;
public void InitDestinationSetListener(GameObject markerMaker)
{
if (markerMaker)
{
foreach (var worldMarker in markerMaker.GetComponents<VRTK_DestinationMarker>())
{
worldMarker.DestinationMarkerSet += new DestinationMarkerEventHandler(DoTeleport);
worldMarker.SetInvalidTarget(ignoreTargetWithTagOrClass);
worldMarker.SetNavMeshCheck(limitToNavMesh);
worldMarker.SetHeadsetPositionCompensation(headsetPositionCompensation);
}
}
}
protected virtual void Start()
{
Utilities.SetPlayerObject(this.gameObject, VRTK_PlayerObject.ObjectTypes.CameraRig);
adjustYForTerrain = false;
eyeCamera = Utilities.AddCameraFade();
InitDestinationMarkerListeners();
InitHeadsetCollisionListener();
enableTeleport = true;
}
protected void OnTeleporting(object sender, DestinationMarkerEventArgs e)
{
if (Teleporting != null)
Teleporting(this, e);
}
protected void OnTeleported(object sender, DestinationMarkerEventArgs e)
{
if (Teleported != null)
Teleported(this, e);
}
protected virtual void Blink(float transitionSpeed)
{
fadeInTime = transitionSpeed;
SteamVR_Fade.Start(Color.black, 0);
Invoke("ReleaseBlink", blinkPause);
}
protected virtual bool ValidLocation(Transform target)
{
//If the target is one of the player objects or a UI Canvas then it's never a valid location
if(target.GetComponent<VRTK_PlayerObject>() || target.GetComponent<VRTK_UIGraphicRaycaster>())
{
return false;
}
bool validNavMeshLocation = false;
if (target)
{
NavMeshHit hit;
validNavMeshLocation = NavMesh.SamplePosition(target.position, out hit, 1.0f, NavMesh.AllAreas);
}
if (!limitToNavMesh)
{
validNavMeshLocation = true;
}
return (validNavMeshLocation && target && target.tag != ignoreTargetWithTagOrClass && target.GetComponent(ignoreTargetWithTagOrClass) == null);
}
protected virtual void DoTeleport(object sender, DestinationMarkerEventArgs e)
{
if (enableTeleport && ValidLocation(e.target) && e.enableTeleport)
{
OnTeleporting(sender, e);
Vector3 newPosition = GetNewPosition(e.destinationPosition, e.target);
CalculateBlinkDelay(blinkTransitionSpeed, newPosition);
Blink(blinkTransitionSpeed);
SetNewPosition(newPosition, e.target);
OnTeleported(sender, e);
}
}
protected virtual void SetNewPosition(Vector3 position, Transform target)
{
this.transform.position = CheckTerrainCollision(position, target);
}
protected virtual Vector3 GetNewPosition(Vector3 tipPosition, Transform target)
{
float newX = 0;
float newY = 17;
float newZ = 0;
return new Vector3(newX, newY, newZ);
}
protected Vector3 CheckTerrainCollision(Vector3 position, Transform target)
{
if (adjustYForTerrain && target.GetComponent<Terrain>())
{
var terrainHeight = Terrain.activeTerrain.SampleHeight(position);
position.y = (terrainHeight > position.y ? position.y : terrainHeight);
}
return position;
}
private void CalculateBlinkDelay(float blinkSpeed, Vector3 newPosition)
{
blinkPause = 0f;
if (distanceBlinkDelay > 0f)
{
float distance = Vector3.Distance(this.transform.position, newPosition);
blinkPause = Mathf.Clamp((distance * blinkTransitionSpeed) / (maxBlinkDistance - distanceBlinkDelay), 0, maxBlinkTransitionSpeed);
blinkPause = (blinkSpeed <= 0.25 ? 0f : blinkPause);
}
}
private void ReleaseBlink()
{
SteamVR_Fade.Start(Color.clear, fadeInTime);
fadeInTime = 0f;
}
private void InitDestinationMarkerListeners()
{
var controllerManager = GameObject.FindObjectOfType<SteamVR_ControllerManager>();
InitDestinationSetListener(controllerManager.left);
InitDestinationSetListener(controllerManager.right);
foreach (var destinationMarker in GameObject.FindObjectsOfType<VRTK_DestinationMarker>())
{
if (destinationMarker.gameObject != controllerManager.left && destinationMarker.gameObject != controllerManager.right)
{
InitDestinationSetListener(destinationMarker.gameObject);
}
}
}
private void InitHeadsetCollisionListener()
{
var headset = GameObject.FindObjectOfType<VRTK_HeadsetCollisionFade>();
if (headset)
{
headset.HeadsetCollisionDetect += new HeadsetCollisionEventHandler(DisableTeleport);
headset.HeadsetCollisionEnded += new HeadsetCollisionEventHandler(EnableTeleport);
}
}
private void DisableTeleport(object sender, HeadsetCollisionEventArgs e)
{
enableTeleport = false;
}
private void EnableTeleport(object sender, HeadsetCollisionEventArgs e)
{
enableTeleport = true;
}
}
And here is the code for the pointer:
namespace VRTK{
using UnityEngine;
using System.Collections;
public class VRTK_BezierPointer : VRTK_WorldPointer
{
public float pointerLength = 10f;
public int pointerDensity = 10;
public bool showPointerCursor = true;
public float pointerCursorRadius = 0.5f;
public float beamCurveOffset = 1f;
public GameObject customPointerTracer;
public GameObject customPointerCursor;
public LayerMask layersToIgnore = Physics.IgnoreRaycastLayer;
private GameObject projectedBeamContainer;
private GameObject projectedBeamForward;
private GameObject projectedBeamJoint;
private GameObject projectedBeamDown;
private GameObject pointerCursor;
private GameObject curvedBeamContainer;
private CurveGenerator curvedBeam;
// Use this for initialization
protected override void Start()
{
base.Start();
InitProjectedBeams();
InitPointer();
TogglePointer(false);
}
protected override void Update()
{
base.Update();
if (projectedBeamForward.gameObject.activeSelf)
{
ProjectForwardBeam();
ProjectDownBeam();
DisplayCurvedBeam();
SetPointerCursor();
}
}
protected override void InitPointer()
{
pointerCursor = (customPointerCursor ? Instantiate(customPointerCursor) : CreateCursor());
pointerCursor.name = string.Format("[{0}]WorldPointer_BezierPointer_PointerCursor", this.gameObject.name);
Utilities.SetPlayerObject(pointerCursor, VRTK_PlayerObject.ObjectTypes.Pointer);
pointerCursor.layer = LayerMask.NameToLayer("Ignore Raycast");
pointerCursor.SetActive(false);
curvedBeamContainer = new GameObject(string.Format("[{0}]WorldPointer_BezierPointer_CurvedBeamContainer", this.gameObject.name));
Utilities.SetPlayerObject(curvedBeamContainer, VRTK_PlayerObject.ObjectTypes.Pointer);
curvedBeamContainer.SetActive(false);
curvedBeam = curvedBeamContainer.gameObject.AddComponent<CurveGenerator>();
curvedBeam.transform.parent = null;
curvedBeam.Create(pointerDensity, pointerCursorRadius, customPointerTracer);
base.InitPointer();
}
protected override void SetPointerMaterial()
{
if (pointerCursor.GetComponent<Renderer>())
{
pointerCursor.GetComponent<Renderer>().material = pointerMaterial;
}
foreach (Renderer mr in pointerCursor.GetComponentsInChildren<Renderer>())
{
mr.material = pointerMaterial;
}
base.SetPointerMaterial();
}
protected override void TogglePointer(bool state)
{
state = (pointerVisibility == pointerVisibilityStates.Always_On ? true : state);
projectedBeamForward.gameObject.SetActive(state);
projectedBeamJoint.gameObject.SetActive(state);
projectedBeamDown.SetActive(state);
}
protected override void DisablePointerBeam(object sender, ControllerInteractionEventArgs e)
{
base.DisablePointerBeam(sender, e);
TogglePointerCursor(false);
curvedBeam.TogglePoints(false);
}
protected override void OnDestroy()
{
base.OnDestroy();
if (projectedBeamDown != null)
{
Destroy(projectedBeamDown);
}
if (pointerCursor != null)
{
Destroy(pointerCursor);
}
if (curvedBeam != null)
{
Destroy(curvedBeam);
}
if (projectedBeamContainer != null)
{
Destroy(projectedBeamContainer);
}
if (curvedBeamContainer != null)
{
Destroy(curvedBeamContainer);
}
}
private GameObject CreateCursor()
{
var cursorYOffset = 0.02f;
var cursor = GameObject.CreatePrimitive(PrimitiveType.Cylinder);
cursor.GetComponent<MeshRenderer>().shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off;
cursor.GetComponent<MeshRenderer>().receiveShadows = false;
cursor.transform.localScale = new Vector3(pointerCursorRadius, cursorYOffset, pointerCursorRadius);
Destroy(cursor.GetComponent<CapsuleCollider>());
return cursor;
}
private void TogglePointerCursor(bool state)
{
var pointerCursorState = (showPointerCursor && state ? showPointerCursor : false);
var playAreaCursorState = (showPlayAreaCursor && state ? showPlayAreaCursor : false);
pointerCursor.gameObject.SetActive(pointerCursorState);
base.TogglePointer(playAreaCursorState);
}
private void InitProjectedBeams()
{
projectedBeamContainer = new GameObject(string.Format("[{0}]WorldPointer_BezierPointer_ProjectedBeamContainer", this.gameObject.name));
Utilities.SetPlayerObject(projectedBeamContainer, VRTK_PlayerObject.ObjectTypes.Pointer);
projectedBeamContainer.transform.parent = this.transform;
projectedBeamContainer.transform.localPosition = Vector3.zero;
projectedBeamForward = new GameObject(string.Format("[{0}]WorldPointer_BezierPointer_ProjectedBeamForward", this.gameObject.name));
Utilities.SetPlayerObject(projectedBeamForward, VRTK_PlayerObject.ObjectTypes.Pointer);
projectedBeamForward.transform.parent = projectedBeamContainer.transform;
projectedBeamJoint = new GameObject(string.Format("[{0}]WorldPointer_BezierPointer_ProjectedBeamJoint", this.gameObject.name));
Utilities.SetPlayerObject(projectedBeamJoint, VRTK_PlayerObject.ObjectTypes.Pointer);
projectedBeamJoint.transform.parent = projectedBeamContainer.transform;
projectedBeamJoint.transform.localScale = new Vector3(0.01f, 0.01f, 0.01f);
projectedBeamDown = new GameObject(string.Format("[{0}]WorldPointer_BezierPointer_ProjectedBeamDown", this.gameObject.name));
Utilities.SetPlayerObject(projectedBeamDown, VRTK_PlayerObject.ObjectTypes.Pointer);
}
private float GetForwardBeamLength()
{
var actualLength = pointerLength;
Ray pointerRaycast = new Ray(transform.position, transform.forward);
RaycastHit collidedWith;
var hasRayHit = Physics.Raycast(pointerRaycast, out collidedWith, pointerLength, ~layersToIgnore);
//reset if beam not hitting or hitting new target
if (!hasRayHit || (pointerContactTarget && pointerContactTarget != collidedWith.transform))
{
pointerContactDistance = 0f;
}
//check if beam has hit a new target
if (hasRayHit)
{
pointerContactDistance = collidedWith.distance;
}
//adjust beam length if something is blocking it
if (hasRayHit && pointerContactDistance < pointerLength)
{
actualLength = pointerContactDistance;
}
return actualLength;
}
private void ProjectForwardBeam()
{
var setThicknes = 0.01f;
var setLength = GetForwardBeamLength();
//if the additional decimal isn't added then the beam position glitches
var beamPosition = setLength / (2 + 0.00001f);
projectedBeamForward.transform.localScale = new Vector3(setThicknes, setThicknes, setLength);
projectedBeamForward.transform.localPosition = new Vector3(0f, 0f, beamPosition);
projectedBeamJoint.transform.localPosition = new Vector3(0f, 0f, setLength - (projectedBeamJoint.transform.localScale.z / 2));
projectedBeamContainer.transform.localRotation = Quaternion.identity;
}
private void ProjectDownBeam()
{
projectedBeamDown.transform.position = new Vector3(projectedBeamJoint.transform.position.x, projectedBeamJoint.transform.position.y, projectedBeamJoint.transform.position.z);
Ray projectedBeamDownRaycast = new Ray(projectedBeamDown.transform.position, Vector3.down);
RaycastHit collidedWith;
var downRayHit = Physics.Raycast(projectedBeamDownRaycast, out collidedWith, float.PositiveInfinity, ~layersToIgnore);
if (!downRayHit || (pointerContactTarget && pointerContactTarget != collidedWith.transform))
{
if (pointerContactTarget != null)
{
base.PointerOut();
}
pointerContactTarget = null;
destinationPosition = Vector3.zero;
}
if (downRayHit)
{
projectedBeamDown.transform.position = new Vector3(projectedBeamJoint.transform.position.x, projectedBeamJoint.transform.position.y - collidedWith.distance, projectedBeamJoint.transform.position.z);
projectedBeamDown.transform.localScale = new Vector3(0.1f, 0.1f, 0.1f);
pointerContactTarget = collidedWith.transform;
destinationPosition = projectedBeamDown.transform.position;
base.PointerIn();
}
}
private void SetPointerCursor()
{
if (pointerContactTarget != null)
{
TogglePointerCursor(true);
pointerCursor.transform.position = projectedBeamDown.transform.position;
base.SetPlayAreaCursorTransform(pointerCursor.transform.position);
UpdatePointerMaterial(pointerHitColor);
}
else
{
TogglePointerCursor(false);
UpdatePointerMaterial(pointerMissColor);
}
}
private void DisplayCurvedBeam()
{
Vector3[] beamPoints = new Vector3[]
{
this.transform.position,
projectedBeamJoint.transform.position + new Vector3(0f, beamCurveOffset, 0f),
projectedBeamDown.transform.position,
projectedBeamDown.transform.position,
};
curvedBeam.SetPoints(beamPoints, pointerMaterial);
if (pointerVisibility != pointerVisibilityStates.Always_Off)
{
curvedBeam.TogglePoints(true);
}
}
}
}

How are you trying to pick the object. Do you use some sort of ray cast or just pick up on collision ? Nevertheless whatever you want to do triggering the teleportation when the object is picked up should be as simple as calling the teleport script from whatever script you using to pick up the object.
for eg:
void OnTriggerEnter(Collider other)
{
if (other.gameObject.CompareTag ("Pick Up"))
{
<<call your teleport script here>>
}
}
Unity has really nice documentation for scripting and you can find a lot of tutorials that explain the basics, even if you go through one of them you should be able to do mostly anything you want with relative ease.

Related

Unity Object Reference Not Set To An Instance Of An Object [duplicate]

This question already has answers here:
What is a NullReferenceException, and how do I fix it?
(27 answers)
Closed 9 months ago.
I have a stanza of code that sees if a collider is intersecting with another collider, but it's giving me an error. I've pasted the error below.
NullReferenceException: Object reference not set to an instance of an object
Portal.LateUpdate () (at Assets/Scripts/Portal.cs:112)
I have no idea why this is happening. Thanks for the help in advance! <3
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Portal : MonoBehaviour
{
//Portal Camera Positioning
public Portal linkedPortal;
Camera portalCam;
Camera playerCam;
//Portal Sceen Texture and Clipping Protection
[HideInInspector]
public PortalScreen portalScreen;
MeshRenderer screenRen;
RenderTexture viewTexture;
public PortalTraveller activeTraveller;
public Collider travellerCollider;
List<PortalTraveller> travellersInPortalColliders;
//Travellers
[HideInInspector]
public List<PortalTraveller> trackedTravellers;
Vector3 desiredCameraRotation;
Vector3 desiredCameraPosition;
Transform globalRuler;
public PortalTraveller[] travellersToAdd;
[HideInInspector]
public float travellerDistance;
//Debug
[HideInInspector]
public float dstToPlayer;
void Awake()
{
playerCam = Camera.main;
portalCam = linkedPortal.GetComponentInChildren<Camera>();
portalScreen = GetComponentInChildren<PortalScreen>();
screenRen = portalScreen.GetComponent<MeshRenderer>();
globalRuler = GameObject.FindWithTag("GlobalRuler").transform;
trackedTravellers = new List<PortalTraveller>();
travellersToAdd = GameObject.FindObjectsOfType<PortalTraveller>();
foreach (PortalTraveller traveller in travellersToAdd)
{
if (!trackedTravellers.Contains(traveller))
{
trackedTravellers.Add(traveller);
}
}
}
void Update()
{
Render();
if (activeTraveller != null)
travellerCollider = activeTraveller.GetComponent<Collider>();
}
static bool VisibleFromCamera(Renderer renderer, Camera camera)
{
Plane[] frustumPlanes = GeometryUtility.CalculateFrustumPlanes(camera);
return GeometryUtility.TestPlanesAABB(frustumPlanes, renderer.bounds);
}
void Render()
{
if (!VisibleFromCamera(screenRen, playerCam))
{
return;
}
desiredCameraPosition = transform.position - (playerCam.transform.position - linkedPortal.portalScreen.screenPos);
desiredCameraPosition.y = playerCam.transform.position.y;
desiredCameraRotation = playerCam.transform.eulerAngles + new Vector3 (0f, 180f, 0f);
portalCam.transform.position = desiredCameraPosition;
portalCam.transform.eulerAngles = desiredCameraRotation;
if (viewTexture == null || viewTexture.width != Screen.width || viewTexture.height != Screen.height)
{
if (viewTexture != null)
{
viewTexture.Release();
}
screenRen.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.ShadowsOnly;
viewTexture = new RenderTexture (Screen.width, Screen.height, 0);
portalCam.targetTexture = viewTexture;
screenRen.material.SetTexture("_MainTex", viewTexture);
screenRen.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.On;
}
}
void LateUpdate()
{
HandleTravellers();
foreach (PortalTraveller traveller in travellersToAdd)
{
if (!trackedTravellers.Contains(traveller))
{
trackedTravellers.Add(traveller);
}
}
foreach (PortalTraveller traveller in trackedTravellers)
{
if (!travellersInPortalColliders.Contains(traveller))
{
traveller.hasTeleported = false;
}
}
}
void HandleTravellers()
{
for (int i = 0; i < trackedTravellers.Count; i++)
{
PortalTraveller traveller = trackedTravellers[i];
Transform travellerT = trackedTravellers[i].transform;
Vector3 toTraveller = traveller.transform.position - transform.position;
int portalSide = System.Math.Sign(Vector3.Dot(toTraveller, transform.right));
int portalSideOld = System.Math.Sign(Vector3.Dot(traveller.previousTravellerVector, transform.right));
travellerDistance = Mathf.Abs(Vector3.Distance(transform.position, travellerT.position));
activeTraveller = traveller;
if (travellerDistance > linkedPortal.travellerDistance)
{
break;
}
if (portalSide != portalSideOld && travellerDistance < globalRuler.transform.lossyScale.z / 2)
{
var positionOld = travellerT.position;
var rotationOld = travellerT.rotation;
Quaternion rot = Quaternion.Euler(desiredCameraRotation.x, desiredCameraRotation.y, 0f);
traveller.Teleport(transform, linkedPortal.transform, travellerT);
traveller.previousTravellerVector = toTraveller;
trackedTravellers.RemoveAt(i);
i--;
}
else
{
traveller.previousTravellerVector = toTraveller;
dstToPlayer = Mathf.Abs(Vector3.Distance(transform.position, travellerT.position));
}
}
}
void OnValidate()
{
if (linkedPortal != null)
{
linkedPortal.linkedPortal = this;
}
travellersToAdd = GameObject.FindObjectsOfType<PortalTraveller>();
}
void OnTriggerEnter(Collider other)
{
if (other.GetComponent<PortalTraveller>() != null)
{
var travellerSharedCollider = other.GetComponent<PortalTraveller>();
if (!travellersInPortalColliders.Contains(travellerSharedCollider))
{
travellersInPortalColliders.Add(travellerSharedCollider);
linkedPortal.travellersInPortalColliders.Add(travellerSharedCollider);
}
}
}
void OnTriggerExit(Collider other)
{
if (other.GetComponent<PortalTraveller>() != null)
{
var travellerSharedCollider = other.GetComponent<PortalTraveller>();
if (travellersInPortalColliders.Contains(travellerSharedCollider))
{
travellersInPortalColliders.Remove(travellerSharedCollider);
linkedPortal.travellersInPortalColliders.Remove(travellerSharedCollider);
}
}
}
}
The reason for the NullReferenceException is because the variable List travellersInPortalColliders is never initialized. You need to somewhere in your code put:
travellersInPortalColliders = new List<PortalTraveller>();
I would suggest somewhere in your awake function. For Example:
void Awake()
{
playerCam = Camera.main;
portalCam = linkedPortal.GetComponentInChildren<Camera>();
portalScreen = GetComponentInChildren<PortalScreen>();
screenRen = portalScreen.GetComponent<MeshRenderer>();
globalRuler = GameObject.FindWithTag("GlobalRuler").transform;
trackedTravellers = new List<PortalTraveller>();
travellersToAdd = GameObject.FindObjectsOfType<PortalTraveller>();
travellersInPortalColliders = new List<PortalTraveller>();
foreach (PortalTraveller traveller in travellersToAdd)
{
if (!trackedTravellers.Contains(traveller))
{
trackedTravellers.Add(traveller);
}
}
}

How do I fix music in my Unity project which randomly bugs when I run the Gameplay scene?

So I recently finished Sebastian Lague's Create a Game series and everything works fine except for the music. I don't know the cause of issue but while in gameplay scene another theme just starts playing, same thing happens when I restart the game and this also happens in Sebastian's finale version of the game so I can't find the answer there. I didn't really try anything since I don't have an idea what cause of the issue may be, so I decided to write here and maybe someone will know the answer. Thanks in advance!
Audio Manager:
using UnityEngine;
using System.Collections;
using UnityEngine.SceneManagement;
public class AudioManager : MonoBehaviour
{
public enum AudioChannel { Master, Sfx, Music };
public float masterVolumePercent { get; private set; }
public float sfxVolumePercent { get; private set; }
public float musicVolumePercent { get; private set; }
private AudioSource sfx2DSource;
private AudioSource[] musicSources;
private int activeMusicSourceIndex;
public static AudioManager instance;
private Transform audioListener;
private Transform playerT;
private SoundLibrary library;
private void OnEnable()
{
SceneManager.sceneLoaded += OnLevelFinishedLoading;
}
private void OnDisable()
{
SceneManager.sceneLoaded -= OnLevelFinishedLoading;
}
void Awake()
{
if (instance != null)
{
Destroy(gameObject);
}
else
{
instance = this;
DontDestroyOnLoad(gameObject);
library = GetComponent<SoundLibrary>();
musicSources = new AudioSource[2];
for (int i = 0; i < 2; i++)
{
GameObject newMusicSource = new GameObject("Music source " + (i + 1));
musicSources[i] = newMusicSource.AddComponent<AudioSource>();
newMusicSource.transform.parent = transform;
}
GameObject newSfx2Dsource = new GameObject("2D sfx source");
sfx2DSource = newSfx2Dsource.AddComponent<AudioSource>();
newSfx2Dsource.transform.parent = transform;
audioListener = FindObjectOfType<AudioListener>().transform;
if (FindObjectOfType<PlayerInput>() != null)
{
playerT = FindObjectOfType<PlayerInput>().transform;
}
masterVolumePercent = PlayerPrefs.GetFloat("master vol", 1);
sfxVolumePercent = PlayerPrefs.GetFloat("sfx vol", 1);
musicVolumePercent = PlayerPrefs.GetFloat("music vol", 1);
}
}
void Update()
{
if (playerT != null)
{
audioListener.position = playerT.position;
}
}
public void SetVolume(float volumePercent, AudioChannel channel)
{
switch (channel)
{
case AudioChannel.Master:
masterVolumePercent = volumePercent;
break;
case AudioChannel.Sfx:
sfxVolumePercent = volumePercent;
break;
case AudioChannel.Music:
musicVolumePercent = volumePercent;
break;
}
musicSources[0].volume = musicVolumePercent * masterVolumePercent;
musicSources[1].volume = musicVolumePercent * masterVolumePercent;
PlayerPrefs.SetFloat("master vol", masterVolumePercent);
PlayerPrefs.SetFloat("sfx vol", sfxVolumePercent);
PlayerPrefs.SetFloat("music vol", musicVolumePercent);
PlayerPrefs.Save();
}
public void PlayMusic(AudioClip clip, float fadeDuration = 1)
{
activeMusicSourceIndex = 1 - activeMusicSourceIndex;
musicSources[activeMusicSourceIndex].clip = clip;
musicSources[activeMusicSourceIndex].Play();
StartCoroutine(AnimateMusicCrossfade(fadeDuration));
}
public void PlaySound(AudioClip clip, Vector3 pos)
{
if (clip != null)
{
AudioSource.PlayClipAtPoint(clip, pos, sfxVolumePercent * masterVolumePercent);
}
}
public void PlaySound(string soundName, Vector3 pos)
{
PlaySound(library.GetClipFromName(soundName), pos);
}
public void PlaySound2D(string soundName)
{
sfx2DSource.PlayOneShot(library.GetClipFromName(soundName), sfxVolumePercent * masterVolumePercent);
}
IEnumerator AnimateMusicCrossfade(float duration)
{
float percent = 0;
while (percent < 1)
{
percent += Time.deltaTime * 1 / duration;
musicSources[activeMusicSourceIndex].volume = Mathf.Lerp(0, musicVolumePercent * masterVolumePercent, percent);
musicSources[1 - activeMusicSourceIndex].volume = Mathf.Lerp(musicVolumePercent * masterVolumePercent, 0, percent);
yield return null;
}
}
private void OnLevelFinishedLoading(Scene scene, LoadSceneMode sceneMode)
{
if (playerT == null)
{
if (FindObjectOfType<PlayerInput>() != null)
playerT = FindObjectOfType<PlayerInput>().transform;
}
}
}
Music Manager:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class MusicManager : MonoBehaviour
{
[SerializeField] private AudioClip mainTheme;
[SerializeField] private AudioClip menuTheme;
private string sceneName;
private void OnEnable()
{
SceneManager.sceneLoaded += OnLevelFinishedLoading;
}
private void OnDisable()
{
SceneManager.sceneLoaded -= OnLevelFinishedLoading;
}
void PlayMusic()
{
AudioClip clipToPlay = null;
if(sceneName == "Main Menu")
{
if(clipToPlay == null)
clipToPlay = menuTheme;
}
else if(sceneName == "Gameplay")
{
if(clipToPlay == null)
clipToPlay = mainTheme;
}
if(clipToPlay != null)
{
AudioManager.instance.PlayMusic(clipToPlay, 2);
Invoke("PlayMusic", clipToPlay.length);
Debug.Log(clipToPlay.length);
}
}
private void OnLevelFinishedLoading(Scene scene, LoadSceneMode sceneMode)
{
if(sceneName != scene.name)
{
sceneName = scene.name;
Invoke("PlayMusic", .2f);
}
}
}

Unity C# script variable not changing in game when changed in script

Very new to Unity, I'm making a tactical RPG game similar to Fire Emblem. I've followed a tutorial on movement from this website and followed everything he did.
The player character can only move 5 tiles in the directions +z, -z, +x, -x on a 12x12 tile grid, however I want it to move 6. In the TacticsMove.cs script, there is this variable: public int move = 5; with the amount of the variable being how many tiles the player moves. I've changed the variable to public int move = 6; and saved the script, but everything is the exact same as before.
I want public int move = 6 to allow the player to move up to 6 tiles instead of 5. There are no comments on the tutorial or youtube videos of this happening so the next place im coming to is here. My code is below, I don't know if all of this is relevant. If you need me to add/remove something, tell me.
TacticsMove.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TacticsMove : MonoBehaviour
{
public bool turn = false;
List<Tile> selectableTiles = new List<Tile>();
GameObject[] tiles;
Stack<Tile> path = new Stack<Tile>();
Tile currentTile;
public bool moving = false;
public int move = 6;
public float jumpHeight = 2;
public float moveSpeed = 2;
public float jumpVelocity = 4.5f;
Vector3 velocity = new Vector3();
Vector3 heading = new Vector3();
float halfHeight = 0;
bool fallingDown = false;
bool jumpingUp = false;
bool movingEdge = false;
Vector3 jumpTarget;
public Tile actualTargetTile;
protected void Init()
{
tiles = GameObject.FindGameObjectsWithTag("Tile");
halfHeight = GetComponent<Collider>().bounds.extents.y;
TurnManager.AddUnit(this);
}
public void GetCurrentTile()
{
currentTile = GetTargetTile(gameObject);
currentTile.current = true;
}
public Tile GetTargetTile(GameObject target)
{
RaycastHit hit;
Tile tile = null;
if (Physics.Raycast(target.transform.position, -Vector3.up, out hit, 1))
{
tile = hit.collider.GetComponent<Tile>();
}
return tile;
}
public void ComputeAdjacencyLists(float jumpHeight, Tile target)
{
//tiles = GameObject.FindGameObjectsWithTag("Tile");
foreach (GameObject tile in tiles)
{
Tile t = tile.GetComponent<Tile>();
t.FindNeighbors(jumpHeight, target);
}
}
public void FindSelectableTiles()
{
ComputeAdjacencyLists(jumpHeight, null);
GetCurrentTile();
Queue<Tile> process = new Queue<Tile>();
process.Enqueue(currentTile);
currentTile.visited = true;
//currentTile.parent = ?? leave as null
while (process.Count > 0)
{
Tile t = process.Dequeue();
selectableTiles.Add(t);
t.selectable = true;
if (t.distance < move)
{
foreach (Tile tile in t.adjacencyList)
{
if (!tile.visited)
{
tile.parent = t;
tile.visited = true;
tile.distance = 1 + t.distance;
process.Enqueue(tile);
}
}
}
}
}
public void MoveToTile(Tile tile)
{
path.Clear();
tile.target = true;
moving = true;
Tile next = tile;
while (next != null)
{
path.Push(next);
next = next.parent;
}
}
public void Move()
{
if (path.Count > 0)
{
Tile t = path.Peek();
Vector3 target = t.transform.position;
//Calculate the unit's position on top of the target tile
target.y += halfHeight + t.GetComponent<Collider>().bounds.extents.y;
if (Vector3.Distance(transform.position, target) >= 0.05f)
{
bool jump = transform.position.y != target.y;
if (jump)
{
Jump(target);
}
else
{
CalculateHeading(target);
SetHorizotalVelocity();
}
//Locomotion
transform.forward = heading;
transform.position += velocity * Time.deltaTime;
}
else
{
//Tile center reached
transform.position = target;
path.Pop();
}
}
else
{
RemoveSelectableTiles();
moving = false;
TurnManager.EndTurn();
}
}
protected void RemoveSelectableTiles()
{
if (currentTile != null)
{
currentTile.current = false;
currentTile = null;
}
foreach (Tile tile in selectableTiles)
{
tile.Reset();
}
selectableTiles.Clear();
}
void CalculateHeading(Vector3 target)
{
heading = target - transform.position;
heading.Normalize();
}
void SetHorizotalVelocity()
{
velocity = heading * moveSpeed;
}
void Jump(Vector3 target)
{
if (fallingDown)
{
FallDownward(target);
}
else if (jumpingUp)
{
JumpUpward(target);
}
else if (movingEdge)
{
MoveToEdge();
}
else
{
PrepareJump(target);
}
}
void PrepareJump(Vector3 target)
{
float targetY = target.y;
target.y = transform.position.y;
CalculateHeading(target);
if (transform.position.y > targetY)
{
fallingDown = false;
jumpingUp = false;
movingEdge = true;
jumpTarget = transform.position + (target - transform.position) / 2.0f;
}
else
{
fallingDown = false;
jumpingUp = true;
movingEdge = false;
velocity = heading * moveSpeed / 3.0f;
float difference = targetY - transform.position.y;
velocity.y = jumpVelocity * (0.5f + difference / 2.0f);
}
}
void FallDownward(Vector3 target)
{
velocity += Physics.gravity * Time.deltaTime;
if (transform.position.y <= target.y)
{
fallingDown = false;
jumpingUp = false;
movingEdge = false;
Vector3 p = transform.position;
p.y = target.y;
transform.position = p;
velocity = new Vector3();
}
}
void JumpUpward(Vector3 target)
{
velocity += Physics.gravity * Time.deltaTime;
if (transform.position.y > target.y)
{
jumpingUp = false;
fallingDown = true;
}
}
void MoveToEdge()
{
if (Vector3.Distance(transform.position, jumpTarget) >= 0.05f)
{
SetHorizotalVelocity();
}
else
{
movingEdge = false;
fallingDown = true;
velocity /= 5.0f;
velocity.y = 1.5f;
}
}
protected Tile FindLowestF(List<Tile> list)
{
Tile lowest = list[0];
foreach (Tile t in list)
{
if (t.f < lowest.f)
{
lowest = t;
}
}
list.Remove(lowest);
return lowest;
}
protected Tile FindEndTile(Tile t)
{
Stack<Tile> tempPath = new Stack<Tile>();
Tile next = t.parent;
while (next != null)
{
tempPath.Push(next);
next = next.parent;
}
if (tempPath.Count <= move)
{
return t.parent;
}
Tile endTile = null;
for (int i = 0; i <= move; i++)
{
endTile = tempPath.Pop();
}
return endTile;
}
protected void FindPath(Tile target)
{
ComputeAdjacencyLists(jumpHeight, target);
GetCurrentTile();
List<Tile> openList = new List<Tile>();
List<Tile> closedList = new List<Tile>();
openList.Add(currentTile);
//currentTile.parent = ??
currentTile.h = Vector3.Distance(currentTile.transform.position, target.transform.position);
currentTile.f = currentTile.h;
while (openList.Count > 0)
{
Tile t = FindLowestF(openList);
closedList.Add(t);
if (t == target)
{
actualTargetTile = FindEndTile(t);
MoveToTile(actualTargetTile);
return;
}
foreach (Tile tile in t.adjacencyList)
{
if (closedList.Contains(tile))
{
//Do nothing, already processed
}
else if (openList.Contains(tile))
{
float tempG = t.g + Vector3.Distance(tile.transform.position, t.transform.position);
if (tempG < tile.g)
{
tile.parent = t;
tile.g = tempG;
tile.f = tile.g + tile.h;
}
}
else
{
tile.parent = t;
tile.g = t.g + Vector3.Distance(tile.transform.position, t.transform.position);
tile.h = Vector3.Distance(tile.transform.position, target.transform.position);
tile.f = tile.g + tile.h;
openList.Add(tile);
}
}
}
//todo - what do you do if there is no path to the target tile?
Debug.Log("Path not found");
}
public void BeginTurn()
{
turn = true;
}
public void EndTurn()
{
turn = false;
}
}
Tile.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Tile : MonoBehaviour
{
public bool walkable = true;
public bool current = false;
public bool target = false;
public bool selectable = false;
public List<Tile> adjacencyList = new List<Tile>();
//Needed BFS (breadth first search)
public bool visited = false;
public Tile parent = null;
public int distance = 0;
//For A*
public float f = 0;
public float g = 0;
public float h = 0;
// Use this for initialization
void Start ()
{
}
// Update is called once per frame
void Update ()
{
if (current)
{
GetComponent<Renderer>().material.color = Color.magenta;
}
else if (target)
{
GetComponent<Renderer>().material.color = Color.green;
}
else if (selectable)
{
GetComponent<Renderer>().material.color = Color.blue;
}
else
{
GetComponent<Renderer>().material.color = Color.white;
}
}
public void Reset()
{
adjacencyList.Clear();
current = false;
target = false;
selectable = false;
visited = false;
parent = null;
distance = 0;
f = g = h = 0;
}
public void FindNeighbors(float jumpHeight, Tile target)
{
Reset();
CheckTile(Vector3.forward, jumpHeight, target);
CheckTile(-Vector3.forward, jumpHeight, target);
CheckTile(Vector3.right, jumpHeight, target);
CheckTile(-Vector3.right, jumpHeight, target);
}
public void CheckTile(Vector3 direction, float jumpHeight, Tile target)
{
Vector3 halfExtents = new Vector3(0.25f, (1 + jumpHeight) / 2.0f, 0.25f);
Collider[] colliders = Physics.OverlapBox(transform.position + direction, halfExtents);
foreach (Collider item in colliders)
{
Tile tile = item.GetComponent<Tile>();
if (tile != null && tile.walkable)
{
RaycastHit hit;
if (!Physics.Raycast(tile.transform.position, Vector3.up, out hit, 1) || (tile == target))
{
adjacencyList.Add(tile);
}
}
}
}
}
PlayerMove.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMove : TacticsMove
{
// Use this for initialization
void Start ()
{
Init();
}
// Update is called once per frame
void Update ()
{
Debug.DrawRay(transform.position, transform.forward);
if (!turn)
{
return;
}
if (!moving)
{
FindSelectableTiles();
CheckMouse();
}
else
{
Move();
}
}
void CheckMouse()
{
if (Input.GetMouseButtonUp(0))
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit))
{
if (hit.collider.tag == "Tile")
{
Tile t = hit.collider.GetComponent<Tile>();
if (t.selectable)
{
MoveToTile(t);
}
}
}
}
}
}
Im using unity version 2019.3.12f1.
Any help is appreciated.
As Etienne de Martel hints, Unity saves your public variables in the scene along with all the other GameObject/Component data, and restores that data on load
Field initializers are the default values for new components, they do not set the values for existing components even with a recompile.
I've been through this a few times myself.
From what I know, variables that have been serialized (which means it is visible in the inspector using [serialize] or it is set to public) will always overwrite scripts. This means that the moment u save ur script after u have create a variable and before u start the program, it can only be adjusted using the inspector

Unity - Physics.OverlapSphere is not detecting instantiated GameObjects

I am having a problem with my RTS game where my enemy units will not attack any base buildings I create after the level starts. They go to attack every other building that was there when the level starts, but none of the built ones.
There is a list being set up of the closest targets to units and they will go to attack their closest target, but any newly instantiated buildings or units, don't get attacked for some reason.
The function DecideWhatToDo() is called on all units in the WorldObject script when they are not doing anything. It then calls FindNearbyObjects() from the WorkManager script.
Everything works up until new units and buildings are created, has anyone experienced this kind of problem before?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
using RTS;
public class WorldObject : MonoBehaviour {
BoxCollider boxCollider;
bool isDead;
bool isSinking;
public string objectName;
public Texture2D buildImage;
public int cost, sellValue, maxHitPoints;
public float hitPoints;
public virtual bool IsActive { get { return true; } }
public float weaponRange = 10.0f;
public float weaponRechargeTime = 1.0f;
public float weaponAimSpeed = 1.0f;
public AudioClip attackSound, selectSound, useWeaponSound;
public float attackVolume = 1.0f, selectVolume = 1.0f, useWeaponVolume = 1.0f;
public int ObjectId { get; set; }
public float detectionRange = 20.0f;
public GameObject explosionPrefab, splat;
protected NavMeshAgent agent;
protected AudioElement audioElement;
protected Animator anim;
protected List<WorldObject> nearbyObjects;
protected Rect playingArea = new Rect(0.0f, 0.0f, 0.0f, 0.0f);
protected Player player;
protected string[] actions = { };
protected bool currentlySelected = false;
protected Bounds selectionBounds;
protected GUIStyle healthStyle = new GUIStyle();
protected float healthPercentage = 1.0f;
protected WorldObject target = null;
protected bool attacking = false;
protected bool movingIntoPosition = false;
protected bool aiming = false;
private List<Material> oldMaterials = new List<Material>();
private float currentWeaponChargeTime;
//we want to restrict how many decisions are made to help with game performance
//the default time at the moment is a tenth of a second
private float timeSinceLastDecision = 0.0f, timeBetweenDecisions = 0.1f;
protected virtual void Awake()
{
anim = GetComponent<Animator>();
boxCollider = GetComponent<BoxCollider>();
selectionBounds = ResourceManager.InvalidBounds;
CalculateBounds();
}
protected virtual void Start()
{
agent = GetComponent<NavMeshAgent>();
SetPlayer();
if (player) SetTeamColor();
InitialiseAudio();
}
protected virtual void Update()
{
if (isSinking)
{
this.transform.Translate(-Vector3.up * 2.5f * Time.deltaTime);
}
if (ShouldMakeDecision()) DecideWhatToDo();
currentWeaponChargeTime += Time.deltaTime;
if (attacking && !movingIntoPosition && !aiming)
{
PerformAttack();
}
}
/**
* A child class should only determine other conditions under which a decision should
* not be made. This could be 'harvesting' for a harvester, for example. Alternatively,
* an object that never has to make decisions could just return false.
*/
protected virtual bool ShouldMakeDecision()
{
if (!attacking && !movingIntoPosition && !aiming)
{
//we are not doing anything at the moment
if (timeSinceLastDecision > timeBetweenDecisions)
{
timeSinceLastDecision = 0.0f;
Debug.Log("");
return true;
}
timeSinceLastDecision += Time.deltaTime;
}
return false;
}
protected virtual void DecideWhatToDo()
{
//determine what should be done by the world object at the current point in time
Vector3 currentPosition = transform.position;
nearbyObjects = WorkManager.FindNearbyObjects(currentPosition, detectionRange);
if (CanAttack())
{
List<WorldObject> enemyObjects = new List<WorldObject>();
foreach (WorldObject nearbyObject in nearbyObjects)
{
Resource resource = nearbyObject.GetComponent<Resource>();
if (resource) continue;
if (nearbyObject.GetPlayer() != player) enemyObjects.Add(nearbyObject);
}
WorldObject closestObject = WorkManager.FindNearestWorldObjectInListToPosition(enemyObjects, currentPosition);
if (closestObject)
{
attacking = true;
//agent.isStopped = true;
BeginAttack(closestObject);
}
}
}
public Player GetPlayer()
{
return player;
}
protected virtual void OnGUI()
{
if (currentlySelected && !ResourceManager.MenuOpen) DrawSelection();
}
protected virtual void InitialiseAudio()
{
List<AudioClip> sounds = new List<AudioClip>();
List<float> volumes = new List<float>();
if (attackVolume < 0.0f) attackVolume = 0.0f;
if (attackVolume > 1.0f) attackVolume = 1.0f;
sounds.Add(attackSound);
volumes.Add(attackVolume);
if (selectVolume < 0.0f) selectVolume = 0.0f;
if (selectVolume > 1.0f) selectVolume = 1.0f;
sounds.Add(selectSound);
volumes.Add(selectVolume);
if (useWeaponVolume < 0.0f) useWeaponVolume = 0.0f;
if (useWeaponVolume > 1.0f) useWeaponVolume = 1.0f;
sounds.Add(useWeaponSound);
volumes.Add(useWeaponVolume);
audioElement = new AudioElement(sounds, volumes, objectName + ObjectId, this.transform);
}
public void SetPlayer()
{
player = transform.root.GetComponentInChildren<Player>();
}
public bool IsOwnedBy(Player owner)
{
if (player && player.Equals(owner))
{
return true;
}
else
{
return false;
}
}
public void CalculateBounds()
{
selectionBounds = new Bounds(transform.position, Vector3.zero);
foreach (Renderer r in GetComponentsInChildren<Renderer>())
{
selectionBounds.Encapsulate(r.bounds);
}
}
//!!!!!MULTI SELECTION!!!!!
public virtual void SetSelection(bool selected, Rect playingArea)
{
currentlySelected = selected;
if (selected)
{
if (audioElement != null) audioElement.Play(selectSound);
this.playingArea = playingArea;
}
CalculateBounds();
}
//!!!!!MULTI SELECTION!!!!!
public Bounds GetSelectionBounds()
{
return selectionBounds;
}
public string[] GetActions()
{
return actions;
}
public void SetColliders(bool enabled)
{
Collider[] colliders = GetComponentsInChildren<Collider>();
foreach (Collider collider in colliders) collider.enabled = enabled;
}
public void SetTransparentMaterial(Material material, bool storeExistingMaterial)
{
if (storeExistingMaterial) oldMaterials.Clear();
Renderer[] renderers = GetComponentsInChildren<Renderer>();
foreach (Renderer renderer in renderers)
{
if (storeExistingMaterial) oldMaterials.Add(renderer.material);
renderer.material = material;
}
}
public void RestoreMaterials()
{
Renderer[] renderers = GetComponentsInChildren<Renderer>();
if (oldMaterials.Count == renderers.Length)
{
for (int i = 0; i < renderers.Length; i++)
{
renderers[i].material = oldMaterials[i];
}
}
}
public void SetPlayingArea(Rect playingArea)
{
this.playingArea = playingArea;
}
public virtual void SetHoverState(GameObject hoverObject)
{
//only handle input if owned by a human player and currently selected
if (player && player.human && currentlySelected)
{
//something other than the ground is being hovered over
if (hoverObject.name != "Ground")
{
Player owner = hoverObject.transform.root.GetComponent<Player>();
Unit unit = hoverObject.transform.parent.GetComponent<Unit>();
Building building = hoverObject.transform.parent.GetComponent<Building>();
if (owner)
{ //the object is owned by a player
if (owner.username == player.username) player.hud.SetCursorState(CursorState.Select);
else if (CanAttack()) player.hud.SetCursorState(CursorState.Attack);
else player.hud.SetCursorState(CursorState.Select);
}
else if (unit || building && CanAttack()) player.hud.SetCursorState(CursorState.Attack);
else player.hud.SetCursorState(CursorState.Select);
}
}
}
public virtual bool CanAttack()
{
//default behaviour needs to be overidden by children
return false;
}
public virtual void PerformAction(string actionToPerform)
{
//it is up to children with specific actions to determine what to do with each of those actions
}
public virtual void MouseClick(GameObject hitObject, Vector3 hitPoint, Player controller)
{
//only handle input if currently selected
if (currentlySelected && hitObject && hitObject.name != "Ground")
{
WorldObject worldObject = hitObject.transform.parent.GetComponent<WorldObject>();
//clicked on another selectable object
if (worldObject)
{
Resource resource = hitObject.transform.parent.GetComponent<Resource>();
if (resource && resource.isEmpty()) return;
Player owner = hitObject.transform.root.GetComponent<Player>();
if (owner)
{ //the object is controlled by a player
if (player && player.human)
{ //this object is controlled by a human player
//start attack if object is not owned by the same player and this object can attack, else select
if (player.username != owner.username && CanAttack())
{
BeginAttack(worldObject);
}
else ChangeSelection(worldObject, controller);
}
else ChangeSelection(worldObject, controller);
}
else ChangeSelection(worldObject, controller);
}
}
}
protected virtual void BeginAttack(WorldObject target)
{
//if (audioElement != null) audioElement.Play(attackSound);
this.target = target;
if (TargetInRange())
{
anim.SetBool("Attacking", true);
attacking = true;
PerformAttack();
}
else AdjustPosition();
}
protected void SetTeamColor()
{
TeamColor[] teamColors = GetComponentsInChildren<TeamColor>();
foreach (TeamColor teamColor in teamColors) teamColor.GetComponent<Renderer>().material.color = player.teamColor;
}
protected virtual void DrawSelectionBox(Rect selectBox)
{
GUI.Box(selectBox, "");
CalculateCurrentHealth(0.35f, 0.65f);
DrawHealthBar(selectBox, "");
}
protected virtual void CalculateCurrentHealth(float lowSplit, float highSplit)
{
healthPercentage = (float)hitPoints / (float)maxHitPoints;
if (healthPercentage > highSplit) healthStyle.normal.background = ResourceManager.HealthyTexture;
else if (healthPercentage > lowSplit) healthStyle.normal.background = ResourceManager.DamagedTexture;
else healthStyle.normal.background = ResourceManager.CriticalTexture;
}
protected void DrawHealthBar(Rect selectBox, string label)
{
healthStyle.padding.top = -20;
healthStyle.fontStyle = FontStyle.Bold;
GUI.Label(new Rect(selectBox.x, selectBox.y - 7, selectBox.width * healthPercentage, 5), label, healthStyle);
}
protected virtual void AimAtTarget()
{
aiming = true;
//this behaviour needs to be specified by a specific object
}
private void ChangeSelection(WorldObject worldObject, Player controller)
{
//this should be called by the following line, but there is an outside chance it will not
SetSelection(false, playingArea);
if (controller.SelectedObject) controller.SelectedObject.SetSelection(false, playingArea);
controller.SelectedObject = worldObject;
worldObject.SetSelection(true, controller.hud.GetPlayingArea());
}
private void DrawSelection()
{
GUI.skin = ResourceManager.SelectBoxSkin;
Rect selectBox = WorkManager.CalculateSelectionBox(selectionBounds, playingArea);
//Draw the selection box around the currently selected object, within the bounds of the playing area
GUI.BeginGroup(playingArea);
DrawSelectionBox(selectBox);
GUI.EndGroup();
}
private bool TargetInRange()
{
Vector3 targetLocation = target.transform.position;
Vector3 direction = targetLocation - transform.position;
if (direction.sqrMagnitude < weaponRange * weaponRange)
{
return true;
}
return false;
}
private void AdjustPosition()
{
Unit self = this as Unit;
if (self)
{
movingIntoPosition = true;
Vector3 attackPosition = FindNearestAttackPosition();
self.StartMove(attackPosition);
attacking = true;
}
else
{
attacking = false;
}
}
private Vector3 FindNearestAttackPosition()
{
Vector3 targetLocation = target.transform.position;
Vector3 direction = targetLocation - transform.position;
float targetDistance = direction.magnitude;
float distanceToTravel = targetDistance - (0.9f * weaponRange);
return Vector3.Lerp(transform.position, targetLocation, distanceToTravel / targetDistance);
}
private void PerformAttack()
{
if (!target)
{
attacking = false;
anim.SetBool("Attacking", false);
anim.SetBool("IsRunning", false);
return;
}
if (!TargetInRange())
{
AdjustPosition();
}
else if (!TargetInFrontOfWeapon())
{
AimAtTarget();
}
else if (ReadyToFire())
{
//attacking = true;
UseWeapon();
}
//if (TargetInRange() && (attacking = true))
//{
// AdjustPosition();
//}
}
private bool TargetInFrontOfWeapon()
{
Vector3 targetLocation = target.transform.position;
Vector3 direction = targetLocation - transform.position;
if (direction.normalized == transform.forward.normalized) return true;
else return false;
}
private bool ReadyToFire()
{
if (currentWeaponChargeTime >= weaponRechargeTime)
{
return true;
}
return false;
}
protected virtual void UseWeapon()
{
if (audioElement != null && Time.timeScale > 0) audioElement.Play(useWeaponSound);
currentWeaponChargeTime = 0.0f;
//this behaviour needs to be specified by a specific object
}
public void TakeDamage(float damage)
{
//GameObject.Instantiate(impactVisual, target.transform.position, Quaternion.identity);
hitPoints -= damage;
if (hitPoints <= 0)
{
Instantiate(explosionPrefab, transform.position + new Vector3(0, 5, 0), Quaternion.identity);
Instantiate(splat, transform.position, Quaternion.identity);
Destroy(gameObject);
}
}
}
using UnityEngine;
using System.Collections.Generic;
namespace RTS
{
public static class WorkManager
{
public static Rect CalculateSelectionBox(Bounds selectionBounds, Rect playingArea)
{
//shorthand for the coordinates of the centre of the selection bounds
float cx = selectionBounds.center.x;
float cy = selectionBounds.center.y;
float cz = selectionBounds.center.z;
//shorthand for the coordinates of the extents of the selection bounds
float ex = selectionBounds.extents.x;
float ey = selectionBounds.extents.y;
float ez = selectionBounds.extents.z;
//Determine the screen coordinates for the corners of the selection bounds
List<Vector3> corners = new List<Vector3>();
corners.Add(Camera.main.WorldToScreenPoint(new Vector3(cx + ex, cy + ey, cz + ez)));
corners.Add(Camera.main.WorldToScreenPoint(new Vector3(cx + ex, cy + ey, cz - ez)));
corners.Add(Camera.main.WorldToScreenPoint(new Vector3(cx + ex, cy - ey, cz + ez)));
corners.Add(Camera.main.WorldToScreenPoint(new Vector3(cx - ex, cy + ey, cz + ez)));
corners.Add(Camera.main.WorldToScreenPoint(new Vector3(cx + ex, cy - ey, cz - ez)));
corners.Add(Camera.main.WorldToScreenPoint(new Vector3(cx - ex, cy - ey, cz + ez)));
corners.Add(Camera.main.WorldToScreenPoint(new Vector3(cx - ex, cy + ey, cz - ez)));
corners.Add(Camera.main.WorldToScreenPoint(new Vector3(cx - ex, cy - ey, cz - ez)));
//Determine the bounds on screen for the selection bounds
Bounds screenBounds = new Bounds(corners[0], Vector3.zero);
for (int i = 1; i < corners.Count; i++)
{
screenBounds.Encapsulate(corners[i]);
}
//Screen coordinates start in the bottom left corner, rather than the top left corner
//this correction is needed to make sure the selection box is drawn in the correct place
float selectBoxTop = playingArea.height - (screenBounds.center.y + screenBounds.extents.y);
float selectBoxLeft = screenBounds.center.x - screenBounds.extents.x;
float selectBoxWidth = 2 * screenBounds.extents.x;
float selectBoxHeight = 2 * screenBounds.extents.y;
return new Rect(selectBoxLeft, selectBoxTop, selectBoxWidth, selectBoxHeight);
}
public static GameObject FindHitObject(Vector3 origin)
{
Ray ray = Camera.main.ScreenPointToRay(origin);
RaycastHit hit;
if (Physics.Raycast(ray, out hit, ResourceManager.RayCastLimit)) return hit.collider.gameObject;
return null;
}
public static Vector3 FindHitPoint(Vector3 origin)
{
Ray ray = Camera.main.ScreenPointToRay(origin);
RaycastHit hit;
Debug.DrawRay(ray.origin, ray.direction * ResourceManager.RayCastLimit, Color.yellow);
if (Physics.Raycast(ray, out hit, ResourceManager.RayCastLimit)) return hit.point;
return ResourceManager.InvalidPosition;
}
public static List<WorldObject> FindNearbyObjects(Vector3 position, float range)
{
Collider[] hitColliders = Physics.OverlapSphere(position, range);
HashSet<int> nearbyObjectIds = new HashSet<int>();
List<WorldObject> nearbyObjects = new List<WorldObject>();
for (int i = 0; i < hitColliders.Length; i++)
{
Transform parent = hitColliders[i].transform.parent;
if (parent)
{
WorldObject parentObject = parent.GetComponent<WorldObject>();
if (parentObject && !nearbyObjectIds.Contains(parentObject.ObjectId))
{
nearbyObjectIds.Add (parentObject.ObjectId);
nearbyObjects.Add (parentObject);
}
}
}
return nearbyObjects;
}
public static WorldObject FindNearestWorldObjectInListToPosition(List<WorldObject> objects, Vector3 position)
{
if (objects == null || objects.Count == 0) return null;
WorldObject nearestObject = objects[0];
float sqrDistanceToNearestObject = Vector3.SqrMagnitude(position - nearestObject.transform.position);
for (int i = 1; i < objects.Count; i++)
{
float sqrDistanceToObject = Vector3.SqrMagnitude(position - objects[i].transform.position);
if (sqrDistanceToObject < sqrDistanceToNearestObject)
{
sqrDistanceToNearestObject = sqrDistanceToObject;
nearestObject = objects[i];
}
}
return nearestObject;
}
}
}
The first thing you need to check is if inside
FindNearbyObjects()
The variable
hitColliders = Physics.OverlapSphere(position, range);
Changes it's size when you instantiate new buildings. In case that is not the case, it may be because you are not adding colliders to the buildings when you instantiate them.
However, I think there are better ways for you to detect buildings without using this Physics.OverlapSphere(), which may be expensive in performance. If I were you I will would give a special tag to the buildings (the original and the instantiated ones) and I will use that in my logic to detect them. So they will be potential targets in your method:
DecideWhatToDo()
Here you can read about how to tag the GameObjects:
https://docs.unity3d.com/Manual/Tags.html

Unity3D: How to show GUI.box if condition is true?

I'm making a game in Unity3D with C#. I am using GUI.box to show a healthbar for the mobs, but I only want to show the GUI.box if there is a target.
This is my code at the moment.
public GameObject target;
public bool existsTarget;
// Use this for initialization
void Start()
{
PlayerAttack pa = (PlayerAttack)GetComponent("PlayerAttack");
target = pa.target;
existsTarget = false;
}
// Update is called once per frame
void Update()
{
if(target != null)
existsTarget = true;
else
existsTarget = false;
}
void OnGUI()
{
if(existsTarget)
GUI.Box(new Rect(500, 10, healthBarLength, 20), curHealth + "/" + maxHealth);
else {
GUI.Box(new Rect(Screen.width, 10, healthBarLength, 20), curHealth + "/" + maxHealth);
}
Unfortunately this doesn't show any healthbars at all. Any ideas as to why?
Posting the scripts here after popular demand.
public class Targetting : MonoBehaviour {
public List<Transform> targets;
public List<Transform> items;
public GameObject TheSelectedTarget {get; set;}
private Transform selectedTarget;
private Transform selectedItem;
private Transform myTransform;
// Use this for initialization
void Start () {
targets = new List<Transform>();
items = new List<Transform>();
selectedTarget = null;
selectedItem = null;
myTransform = transform;
TheSelectedTarget = null;
addAllEnemies();
addAllItems();
}
//adds all targets to a list
private void addAllEnemies() {
GameObject[] go = GameObject.FindGameObjectsWithTag("Enemy");
foreach(GameObject enemy in go){
addTarget(enemy.transform);
}
}
//adds a target
private void addTarget(Transform enemy) {
targets.Add(enemy);
}
//sorts target by distance
private void sortTargets() {
targets.Sort(delegate(Transform t1, Transform t2) {
return Vector3.Distance(t1.position, myTransform.position).CompareTo(Vector3.Distance(t2.position, myTransform.position));
});
}
//targets an enemy
private void targetEnemy() {
addAllEnemies();
if(selectedTarget == null) {
sortTargets();
selectedTarget = targets[0];
} else {
int index = targets.IndexOf(selectedTarget);
if(index < targets.Count -1) {
index++;
} else {
index = 0;
}
deselectTarget();
selectedTarget = targets[index];
}
selectTarget();
targets.Clear();
}
//selects a specific target, and colors it red
public void selectTarget() {
selectedTarget.renderer.material.color = Color.red;
PlayerAttack pa = (PlayerAttack)GetComponent("PlayerAttack");
pa.target = selectedTarget.gameObject;
TheSelectedTarget = pa.target;
}
//deselects the current selected target, and colors i grey
private void deselectTarget() {
selectedTarget.renderer.material.color = Color.gray;
selectedTarget = null;
}
//adds all items to a list
void addAllItems() {
GameObject[] go = GameObject.FindGameObjectsWithTag("Book");
foreach(GameObject book in go){
addItem(book.transform);
}
}
'
.... And then the script continues but without any relevance to this...
' public class EnemyHealth : MonoBehaviour
{
public string enemyName;
public int maxHealth = 100;
public int curHealth = 100;
public float healthBarLength;
public GameObject target;
public bool existsTarget;
public AudioSource dying;
// Use this for initialization
void Start()
{
//enemyName = this.enemyName;
healthBarLength = Screen.width / 3;
existsTarget = false;
}
// Update is called once per frame
void Update()
{
adjustCurHealth(0);
Targetting ta = (Targetting)GetComponent("Targetting");
target = ta.TheSelectedTarget;
Debug.Log (target);
if(target != null)
existsTarget = true;
else {
existsTarget = false;
}
}
void OnGUI()
{
if(existsTarget)
GUI.Box(new Rect(500, 10, healthBarLength, 20), curHealth + "/" + maxHealth);
else {
GUI.Box(new Rect(Screen.width, 10, healthBarLength, 20), curHealth + "/" + maxHealth);
}
}
public void adjustCurHealth(int adj)
{
curHealth += adj;
if (curHealth < 0)
curHealth = 0;
if (curHealth > 100)
curHealth = 100;
if (maxHealth < 0)
maxHealth = 1;
if(curHealth == 0)
{
//dying.Play ();
GameObject.Destroy(gameObject);
}
healthBarLength = (Screen.width / 3) * (curHealth / (float)maxHealth);
}
}
Are you ever setting the target anywhere other than the Start() method? The code you show will only ever show a GUI.box if the PlayerAttack.Target is not null at the start. Try moving this code to the Update() method.
PlayerAttack pa = (PlayerAttack)GetComponent("PlayerAttack");
target = pa.target;
Edit:
Check to see if the target is null, that could be the issue.
target = pa.target;
Debug.Log(target);
This will either print to the log as whatever GameObject it is, or null. If it's null, then there is no target.

Categories