Be the first to post for 'Using Gizmos To Visualise Code'!

If you’re reading this, there probably aren’t very many posts yet. But don’t worry, you can be the first! Either create a new post or just reply to this one to say ‘hi’.

1 Like

Found a bug issue here as i have a custom camera i need a confirmation its not just me.
On entering controller/keyboard controls with the G key the gizmos remain static on the floor.
I am guessing its a simple matter of turning gizmos on and off on the keypress. Will post back when i figure it out.

Edit

void OnDrawGizmos()
{
    if (!isInDirectMode)
    {
        // Draw Movement Gizmos
        Gizmos.color = Color.black;
        Gizmos.DrawLine(transform.position, currentDestination);
        Gizmos.DrawSphere(currentDestination, 0.1f);
        Gizmos.DrawSphere(clickPoint, 0.15f);
        // Draw attack Sphere
        Gizmos.color = new Color(255f, 0f, 0f, 0.5f);
        Gizmos.DrawWireSphere(transform.position, attackMoveStopRadius);
    }
    else
    {
        return;
    }
}
1 Like

I’m not exactly sure what you are saying but clickPoint and currentDestination only get changed inside of the mouse click event. ( if (Input.GetMouseButton(0)) ) …so these will not change if you switch to a controller and start moving around. I’m assuming we aren’t going to do gizmos for controllers … at least not the click to point stuff since that doesnt really make sense with a controller stick.

Also, because you are saying if NOT isindirectmode, then even the wiresphere wont change when you are in controller mode. Hope that helps some?

And heres my pic for the group.

Here’s just a tip in case you would rather draw a circle, not a wire sphere with all the additional lines you don’t really need. Just add a method like this to PlayerMovement script. It draws a lot of small lines in an arch to form a circle.

void GizmosDrawCircle(Vector3 center, float radius, float step = 0.1f) {
    float theta = 0.0f;
    float x = radius * Mathf.Cos(theta);
    float y = radius * Mathf.Sin(theta);
    Vector3 position = center + new Vector3(x, 0, y);
    Vector3 newPosition = position;
    Vector3 lastPosition = position;
    for (theta = step; theta < Mathf.PI * 2; theta += step) {
        x = radius * Mathf.Cos(theta);
        y = radius * Mathf.Sin(theta);
        newPosition = center + new Vector3(x, 0, y);
        Gizmos.DrawLine(position, newPosition);
        position = newPosition;
    }
    Gizmos.DrawLine(position, lastPosition);
}

And call it from the OnDrawGizmos() method:
GizmosDrawCircle(transform.position, attackMoveStopRadius);
instead of Gizmos.DrawWireSphere().

8 Likes

i think an easy way to draw a cricle is just use UnityEditor.Handles.DrawWireDisc(position,normal,radius); :blush: thats what i did.

5 Likes


Maybe less Gizmos…:joy::joy:

2 Likes

With reference to the following codes, my character will move to the destination and start spinning around (not staying still). This issue was fixed in the last video when a braking distance code was put in place. However, with the new code in this video, the issue is back.

private void WalkToDestination()
{
var playerToClickPoint = currentDestination - transform.position;
if (playerToClickPoint.magnitude >= 0)
{
thirdPersonCharacter.Move(playerToClickPoint, false, false);
}
thirdPersonCharacter.Move(Vector3.zero, false, false);
}

It seems that playerToClickPoint.magnitude drops to a value close to 0, about 0.2, so the code to stop the player movement was never executed. So changing the code to if (playerToClickPoint.magnitude >= 0.2f) will resolve the issue, but is that the correct way to resolve it?

Any advice please?

Thank you!

Hi, I had the same issue as you and I just replace the 0 with the walkMoveStopRadius value (so every time you change it change the value)

The bug occurs because of a logic error in the code. Prior to adding the ShortDestination function, the player would walk toward the destination until he/she was within the walkMoveStopRadius distance away (this is in the line “if (playerToClickPoint >= walkMoveStopRadius)”). With the addition of the ShortDestination function, the calculation for the point occurs before the player attempts to walk to it. So the player is now trying to reach an exact point the walkMoveStopRadius distance away from where you clicked, displayed in the line “if(playerToClickPoint.magnitude >= 0f)”.

Re-adding “if (playerToClickPoint >= walkMoveStopRadius)” as opposed to 0 will fix the issue, BUT now your player will stop twice the walkMoveStopRadius away from where you click. This is because the destination has already been shortened by that amount and then you walk to that distance away from destination again, meaning movement clicks are becoming less precise.

I don’t have a particularly eloquent solution yet, besides reverting the walk movement calculations back to how they were before adding the ShortDestination function and then only using the ShortDestination function for the attack stop calculations. I am hoping a better solution is found later through the lessons.

1 Like

I confirm the problem but i’ve found a solution (not perfect tho)

I’ve added a variable where i store the last computed magnitude distance and then check that value into the WalkToDestination method, in order to prevent the bug happening again, while preserving the correct distance stored in the radius

I past the whole class here for reference

using System;
using UnityEngine;
using UnityStandardAssets.Characters.ThirdPerson;
using UnityStandardAssets.CrossPlatformInput;

[RequireComponent(typeof(ThirdPersonCharacter))]
public class PlayerMovement : MonoBehaviour {
	ThirdPersonCharacter _character;   // A reference to the ThirdPersonCharacter on the object
	CameraRaycaster cameraRaycaster;

	/// <summary>
	/// current player destination
	/// </summary>
	Vector3 currentDestination;

	/// <summary>
	/// location where the mouse has been clicked
	/// </summary>
	Vector3 clickPoint;
	[SerializeField]
	float walkMoveStopRadius = 0.2f;

	[SerializeField]
	float attackMoveStopRadius = 5f;

	/// <summary>
	/// is the player moved by direct commands? (gamepad/keyboard)
	/// </summary>
	bool _isInDirectMode = false;

	private bool _isCrouching;
	private bool _isJumping;

	private float _previousDistanceMagnitude = 0;

	private void Start() {
		cameraRaycaster = Camera.main.GetComponent<CameraRaycaster>();
		_character = GetComponent<ThirdPersonCharacter>();
		currentDestination = transform.position;
	}


	private void Update() {
		if (!_isJumping) {
			_isJumping = CrossPlatformInputManager.GetButtonDown("Jump");
		}

		//G for gamepad.
		// TODO allow player map key
		if (Input.GetKeyDown(KeyCode.G)) {
			_isInDirectMode = !_isInDirectMode;
			currentDestination = transform.position;
		}
	}

	// Fixed update is called in sync with physics
	private void FixedUpdate() {
		_isCrouching = Input.GetKey(KeyCode.LeftControl);

		if (_isInDirectMode) {
			ProcessDirectMovement();
		}
		else {
			ProcessMouseMovement();
		}

		// pass all parameters to the character control script
		_isJumping = false;
	}

	private void ProcessDirectMovement() {
		// read inputs
		float h = Input.GetAxis("Horizontal");
		float v = Input.GetAxis("Vertical");

		// calculate camera relative direction to move:
		Vector3 camForward = Vector3.Scale(Camera.main.transform.forward, new Vector3(1, 0, 1)).normalized;
		Vector3 move = v * camForward + h * Camera.main.transform.right;

		_character.Move(move, _isCrouching, _isJumping);
	}

	private void ProcessMouseMovement() {
		if (Input.GetMouseButton(0)) {
			clickPoint = cameraRaycaster.hit.point;
			switch (cameraRaycaster.currentLayerHit) {
				case Layer.Walkable:
					currentDestination = ShortDestination(clickPoint, walkMoveStopRadius);
					_previousDistanceMagnitude = float.MaxValue;
					break;
				case Layer.Enemy:
					currentDestination = ShortDestination(clickPoint, attackMoveStopRadius);
					break;
				case Layer.RaycastEndStop:
					break;
				default:
					break;
			}
		}

		WalkToDestination();
	}

	private void WalkToDestination() {
		var playerToClickPoint = currentDestination - transform.position;

		if (_previousDistanceMagnitude > walkMoveStopRadius || (playerToClickPoint.magnitude < _previousDistanceMagnitude)) {
			_character.Move(playerToClickPoint, _isCrouching, _isJumping);
			_previousDistanceMagnitude = playerToClickPoint.magnitude;
		}
		else {
			_character.Move(Vector3.zero, _isCrouching, _isJumping);
		}
	}

	private Vector3 ShortDestination(Vector3 destination, float shortening) {
		Vector3 reductionVector = (destination - transform.position).normalized * shortening;
		return destination - reductionVector;
	}


	void OnDrawGizmos() {
		Gizmos.color = Color.black;
		Gizmos.DrawLine(transform.position, currentDestination);
		Gizmos.color = Color.green;
		Gizmos.DrawSphere(currentDestination, 0.1f);
		Gizmos.color = Color.red;
		Gizmos.DrawSphere(clickPoint, 0.15f);

		//attack Gizmos
		Gizmos.color = Color.red;
		GizmosEx.DrawCircle(transform.position, attackMoveStopRadius);
	}
}

note the _previousDistanceMagnitude variable and check where i use it

P.S.
I borrowed the code posted here by @Rilifaen to draw the circle Gizmo, and to keep it cleaner I’ve created a static class GizmoEx where i want to add other kind of Gizmos in the future, so to keep the code clean and be usable in other places

add a file named GizmosEx.cs in your project with this code

namespace UnityEngine {
	/// <summary>
	/// Extended methods for Gizmos class
	/// </summary>
	public static class GizmosEx {
		public static void DrawCircle(Vector3 center, float radius, float step = 0.1f) {
			float theta = 0.0f;
			float x = radius * Mathf.Cos(theta);
			float y = radius * Mathf.Sin(theta);
			Vector3 position = center + new Vector3(x, 0, y);
			Vector3 newPosition = position;
			Vector3 lastPosition = position;
			for (theta = step; theta < Mathf.PI * 2; theta += step) {
				x = radius * Mathf.Cos(theta);
				y = radius * Mathf.Sin(theta);
				newPosition = center + new Vector3(x, 0, y);
				Gizmos.DrawLine(position, newPosition);
				position = newPosition;
			}
			Gizmos.DrawLine(position, lastPosition);
		}
	}
}

I had choose to do an action-adventure RPG and just made this cone mesh gizmo to help me adjust the line of sight of the player. Very handy.

Is it even possible to have a character movement that includes both one click to run to that point and also hold mouse to run around and stop when mouse is released… i’ve tried everything to get both to work together but it seems impossible .

I’ve implemented the attackMoveStop perfectly and have run through all the code to see where it might be going wrong but I seem to be stuck…

When I click on a walkable layer Ethan moves just fine, when I click on an enemy my clickpoint gizmo appears on the enemy exactly where I clicked but without Ethan moving.

I have as I said checked the code but have also checked layering is correct, also

Anyone else having this issue?


quick take of my gizmos

Does the issue with the player character spinning around on the spot when it gets to its destination get solved in a future lecture?

The change of condition in the WalkToDestination function from playerToClickPoint.magnitude >= walkStopMoveRadius to playerToClickPoint.magnitude >= 0 would seem to make the whole of the if else statement redundant.

I think it does, yes.

Later it switches to the player using a navmesh to move around which appears to resolve it.

hey, hello I don’t know if you fixed this bug already but I had the same issue.
It is easy to fix, just check what I did:
private void WalkToDestination()
{
var playerClickToPoint = currentDestination - transform.position;
if (playerClickToPoint.magnitude > 0.01)
{
thirdPersonCharacter.Move(playerClickToPoint, false, false);
}
else
{
thirdPersonCharacter.Move(Vector3.zero, false, false);
}
}
I put 0.01 because you have to prevent the minimum error possibilities, so it’s very easy. At least it worked for me! hope it helps you. See ya

5 meters seems more like a ranged weapon distance than a melee distance. It just seems YUGE when I try it out and see the gizmo sphere. I would think 1.5 or 2 meters at the very most If you’re hitting the enemy with a sword?

Hello,I don’t seem to even have the player gizmo in my list,also everytime I try to add code I get an error for
feature “local functions” not avail in C#

Privacy & Terms