1
\$\begingroup\$

So I have this helper script that I use to move points around manually while debugging:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
public class MovablePoints : MonoBehaviour
{
public List<Vector2> points = new List<Vector2>();
public List<int> moveablePoints = new List<int>();
[Range(.01f, 1f)] public float selectionRadius = .05f;
public bool selectionActive;
public Vector2 clickedPos;
public List<Vector2> offsets = new List<Vector2>();
private void Update()
{
 Vector2 mosPos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
 if (Input.GetMouseButtonDown(0))
 {
 clickedPos = mosPos;
 for (int i = 0; i < points.Count; i++)
 {
 Vector2 point = points[i];
 if (IsPointInRange(point, mosPos))
 {
 if (!moveablePoints.Contains(i))
 {
 offsets.Add(point - clickedPos);
 moveablePoints.Add(i);
 }
 }
 }
 }
 if (Input.GetMouseButton(0))
 {
 for (int i = 0; i < moveablePoints.Count; i++)
 {
 Vector2 offset = offsets[i];
 points[moveablePoints[i]] = mosPos + offset;
 }
 }
 if (Input.GetMouseButtonUp(0))
 {
 offsets.Clear();
 moveablePoints.Clear();
 }
}
[Range(.001f, .1f)] public float gizmoSize = .05f;
void OnDrawGizmos()
{
 if (selectionActive)
 {
 Color selectionColor = Color.white;
 selectionColor.a = 0.65f;
 Handles.color = selectionColor;
 if (Input.GetAxis("Mouse ScrollWheel") > 0f && selectionRadius < 1)
 selectionRadius += .01f;
 if (Input.GetAxis("Mouse ScrollWheel") < 0f && selectionRadius > 0)
 selectionRadius -= .01f;
 Vector2 mosPos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
 Handles.DrawWireDisc(mosPos, new Vector3(0, 0, 1), selectionRadius);
 for (int i = 0; i < points.Count; i++)
 {
 Vector2 point = points[i];
 if (IsPointInRange(point, mosPos))
 {
 if (Input.GetMouseButton(0) && moveablePoints.Contains(i))
 Gizmos.color = Color.green;
 else
 Gizmos.color = Color.red;
 }
 else
 Gizmos.color = Color.white;
 Gizmos.DrawSphere(point, gizmoSize);
 }
 }
}
bool IsPointInRange(Vector2 point, Vector2 mosPos)
{
 float dx = Mathf.Abs(point.x - mosPos.x);
 float dy = Mathf.Abs(point.y - mosPos.y);
 if (dx > selectionRadius)
 return false;
 if (dy > selectionRadius)
 return false;
 if (dx + dy <= selectionRadius)
 return true;
 if (Mathf.Pow(dx, 2) + Mathf.Pow(dy, 2) <= Mathf.Pow(selectionRadius, 2))
 return true;
 return false;
}
}

This an example of how I use and subscribe points to the "Moveable Points"

public Vector2 A = new Vector2();
public Vector2 B = new Vector2();
public Vector2 C = new Vector2();
private void Start()
{
 movablePoints.points.Add(A);
 movablePoints.points.Add(B);
 movablePoints.points.Add(C);
}
void Update()
{
 A = movablePoints.points[0];
 B = movablePoints.points[1];
 C = movablePoints.points[2];
}

However, if multiple scripts are adding points to the MoveablePoints Script, it gets quite hard to remember what index is where. Is there a way to have the MoveablePoints script update the values of the subscriber automatically? Perhaps through reference?

enter image description here enter image description here

asked Nov 1, 2022 at 5:52
\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

I don't have experience with unity but what is the problem if you make a class represent a point to collect information about each point (position, offset, color,... etc.)

public class Point
{
 public Vector2 Position { get; set; } = new(0, 0);
 public Vector2 Offset { get; set; } = new(0, 0);
 public Color Color { get; set; } = Color.white;
 public bool IsMoving { get; set; } = false;
}

now you can git ride of this three lists

public List<Vector2> points = new List<Vector2>();
public List<int> moveablePoints = new List<int>();
public List<Vector2> offsets = new List<Vector2>();

and only have single list that hold information you need

public List<Point> points = new();

simplify code

Due to Point class now you can get more readable update method

private void Update()
{
 Vector2 mosPos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
 if (Input.GetMouseButtonDown(0))
 {
 foreach(var point in points) 
 { 
 if (IsPointInRange(point.Position, mosPos))
 {
 point.IsMoving = true;
 point.Offset = point.Position - mosPos;
 }
 }
 }
 if (Input.GetMouseButton(0))
 {
 foreach(var point in points)
 {
 if (point.IsMoving)
 point.Position += mosPos + point.Offset;
 }
 }
 if (Input.GetMouseButtonUp(0))
 {
 foreach (var point in points)
 {
 point.IsMoving = false;
 }
 }
}

for the following code

void OnDrawGizmos()
{
 if (selectionActive)
 {
 //.. all the code 
 }
}

it would be cleaner if you use Inverted "if" statement to reduce nesting (one less indentation)

void OnDrawGizmos()
{
 if (!selectionActive) return;
 //.. all the code 
}

for the following pice of code

for (int i = 0; i < points.Count; i++)
{
 Vector2 point = points[i];
 if (IsPointInRange(point, mosPos))
 {
 if (Input.GetMouseButton(0) && moveablePoints.Contains(i))
 Gizmos.color = Color.green;
 else
 Gizmos.color = Color.red;
 }
 else
 Gizmos.color = Color.white;
 Gizmos.DrawSphere(point, gizmoSize);
}

you can drop the nesting because they are not good for readability as following

foreach (var point in points)
{
 bool IsUnderSelectedArea = IsPointInRange(point.Position, mosPos);
 if (point.IsMoving)
 Gizmos.color = Color.green;
 else if (IsUnderSelectedArea)
 Gizmos.color = Color.red;
 else
 Gizmos.color = Color.white;
 Gizmos.DrawSphere(point. Position, gizmoSize);
}

final advice

you shoud move IsPointInRange to Be in the Point class

public class Point
{
 public Vector2 Position { get; set; } = new(0, 0);
 public Vector2 Offset { get; set; } = new(0, 0);
 public Color Color { get; set; } = Color.white;
 public bool IsMoving { get; set; } = false;
 public bool IsInRangeOfmose(Vector2 mosPos, float radiusRange)
 {
 float dx = Mathf.Abs(Position.x - mosPos.x);
 float dy = Mathf.Abs(Position.y - mosPos.y);
 if (dx > radiusRange)
 return false;
 if (dy > radiusRange)
 return false;
 if (dx + dy <= radiusRange)
 return true;
 if (Mathf.Pow(dx, 2) + Mathf.Pow(dy, 2) <= Mathf.Pow(radiusRange, 2))
 return true;
 return false;
 }
}

this will lead to the following syntex

point.IsInRangeOfmose(mosPos, selectionRadius);
answered Nov 2, 2022 at 8:45
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.