Initial commit
This commit is contained in:
196
Assets/Scripts/Constellation.cs
Normal file
196
Assets/Scripts/Constellation.cs
Normal file
@@ -0,0 +1,196 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class Constellation : MonoBehaviour
|
||||
{
|
||||
[Header("Режим малювання")]
|
||||
public bool editMode = false;
|
||||
[Header("Максимальна кількіссть зірок")]
|
||||
public int maxStars = 10;
|
||||
|
||||
[Header("Матеріали")]
|
||||
[SerializeField] private GameObject starPrefab;
|
||||
[SerializeField] private Material lineMaterial;
|
||||
|
||||
[Header("Відстань")]
|
||||
[SerializeField] private float planeDistance = 8f;
|
||||
|
||||
[Header("Розміри")]
|
||||
[SerializeField] private float starScaleMin = 0.06f;
|
||||
[SerializeField] private float starScaleMax = 0.14f;
|
||||
[SerializeField] private float lineWidth = 0.02f;
|
||||
|
||||
private readonly List<Transform> _stars = new List<Transform>();
|
||||
private readonly List<LineRenderer> _lines = new List<LineRenderer>();
|
||||
|
||||
private Transform _root;
|
||||
private Camera _cam;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
EnsureCameraAndRoot();
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (!editMode) return;
|
||||
|
||||
EnsureCameraAndRoot();
|
||||
|
||||
if (_cam == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (Input.GetMouseButtonDown(0))
|
||||
{
|
||||
TryAddStarByClick(Input.mousePosition);
|
||||
}
|
||||
|
||||
UpdateAllLines();
|
||||
}
|
||||
|
||||
private void EnsureCameraAndRoot()
|
||||
{
|
||||
if (_cam == null || !_cam.enabled)
|
||||
{
|
||||
_cam = FindEnabledCamera();
|
||||
}
|
||||
|
||||
if (_cam != null && (_root == null || _root.parent != _cam.transform))
|
||||
{
|
||||
if (_root == null)
|
||||
{
|
||||
GameObject go = new GameObject("ConstellationRoot");
|
||||
_root = go.transform;
|
||||
}
|
||||
|
||||
_root.SetParent(_cam.transform);
|
||||
_root.localPosition = new Vector3(0f, 0f, planeDistance);
|
||||
_root.localRotation = Quaternion.identity;
|
||||
_root.localScale = Vector3.one;
|
||||
}
|
||||
}
|
||||
|
||||
private Camera FindEnabledCamera()
|
||||
{
|
||||
Camera[] cams = Camera.allCameras;
|
||||
for (int i = 0; i < cams.Length; i++)
|
||||
{
|
||||
if (cams[i] != null && cams[i].enabled && cams[i].gameObject.activeInHierarchy)
|
||||
return cams[i];
|
||||
}
|
||||
|
||||
if (Camera.main != null && Camera.main.enabled)
|
||||
return Camera.main;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void TryAddStarByClick(Vector3 screenPos)
|
||||
{
|
||||
Ray ray = _cam.ScreenPointToRay(screenPos);
|
||||
|
||||
Plane plane = new Plane(_cam.transform.forward, _cam.transform.position + _cam.transform.forward * planeDistance);
|
||||
|
||||
if (!plane.Raycast(ray, out float enter))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Vector3 worldHit = ray.GetPoint(enter);
|
||||
Vector3 localHit = _root.InverseTransformPoint(worldHit);
|
||||
|
||||
GameObject starGo = Instantiate(starPrefab, _root);
|
||||
starGo.name = "Star_" + _stars.Count;
|
||||
|
||||
Transform starT = starGo.transform;
|
||||
starT.localPosition = localHit;
|
||||
|
||||
float rndScale = Random.Range(starScaleMin, starScaleMax);
|
||||
starT.localScale = Vector3.one * rndScale;
|
||||
|
||||
_stars.Add(starT);
|
||||
|
||||
if (_stars.Count >= 2)
|
||||
{
|
||||
CreateLine(_stars[_stars.Count - 2], _stars[_stars.Count - 1]);
|
||||
}
|
||||
}
|
||||
|
||||
private void CreateLine(Transform a, Transform b)
|
||||
{
|
||||
if (a == null || b == null) return;
|
||||
|
||||
GameObject lineGo = new GameObject("Line_" + _lines.Count);
|
||||
lineGo.transform.SetParent(_root);
|
||||
lineGo.transform.localPosition = Vector3.zero;
|
||||
lineGo.transform.localRotation = Quaternion.identity;
|
||||
lineGo.transform.localScale = Vector3.one;
|
||||
|
||||
LineRenderer lr = lineGo.AddComponent<LineRenderer>();
|
||||
|
||||
if (lineMaterial != null)
|
||||
{
|
||||
lr.material = lineMaterial;
|
||||
}
|
||||
else
|
||||
{
|
||||
Material fallback = new Material(Shader.Find("Unlit/Color"));
|
||||
fallback.color = new Color(0.7f, 0.85f, 1f, 1f);
|
||||
lr.material = fallback;
|
||||
}
|
||||
|
||||
lr.useWorldSpace = false;
|
||||
lr.positionCount = 2;
|
||||
lr.startWidth = lineWidth;
|
||||
lr.endWidth = lineWidth;
|
||||
|
||||
lr.numCapVertices = 6;
|
||||
lr.numCornerVertices = 6;
|
||||
|
||||
_lines.Add(lr);
|
||||
|
||||
lr.SetPosition(0, a.localPosition);
|
||||
lr.SetPosition(1, b.localPosition);
|
||||
}
|
||||
|
||||
private void UpdateAllLines()
|
||||
{
|
||||
int needed = Mathf.Max(0, _stars.Count - 1);
|
||||
if (_lines.Count < needed) return;
|
||||
|
||||
for (int i = 0; i < needed; i++)
|
||||
{
|
||||
LineRenderer lr = _lines[i];
|
||||
if (lr == null) continue;
|
||||
|
||||
Transform a = _stars[i];
|
||||
Transform b = _stars[i + 1];
|
||||
|
||||
if (a == null || b == null) continue;
|
||||
|
||||
lr.SetPosition(0, a.localPosition);
|
||||
lr.SetPosition(1, b.localPosition);
|
||||
}
|
||||
}
|
||||
|
||||
public void ClearAll()
|
||||
{
|
||||
for (int i = 0; i < _lines.Count; i++)
|
||||
{
|
||||
if (_lines[i] != null) Destroy(_lines[i].gameObject);
|
||||
}
|
||||
|
||||
for (int i = 0; i < _stars.Count; i++)
|
||||
{
|
||||
if (_stars[i] != null) Destroy(_stars[i].gameObject);
|
||||
}
|
||||
|
||||
_lines.Clear();
|
||||
_stars.Clear();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user