using System.Collections.Generic;
using UnityEngine;
namespace ServiceSim
{
///
/// ロボットがいま引いている道を、床の上に細い線で出す(依頼 v9 の 6 章)。
///
/// 色は仕事で変える:
/// 料理を載せているとき(卓へ向かっている)… だいだい
/// 空で戻るとき・待機 … 水色
///
/// 見た目だけ。当たりも NavMesh も持たないので、
/// ロボットのセンサー・人のよけ方・道探しには入らない。
/// RobotSpec.showPathLine を外すと出さない(測る回でも出してよいが、切れるようにする)。
///
/// 置き場所: ロボットの prefab には足さない。ロボットが自分で子として作る
/// (材料も prefab も要らないようにして、シーンの組み立てを変えないため)。
///
[RequireComponent(typeof(LineRenderer))]
public class RobotPathLine : MonoBehaviour
{
/// この部品を置く子の名前
public const string RootName = "PathLine";
static readonly Color CarryColor = new Color(1f, 0.55f, 0.1f, 0.9f); // 料理を載せている
static readonly Color EmptyColor = new Color(0.25f, 0.75f, 1f, 0.9f); // 空で戻る
LineRenderer _line;
readonly List _points = new List();
///
/// ロボットの下に線を作る(無ければ)。材料はその場で作るので、
/// prefab や .asset をいじらなくていい。URP でも読める shader を順に試す
///
public static RobotPathLine Attach(Transform robot, float widthM)
{
if (robot == null) return null;
Transform t = robot.Find(RootName);
GameObject go;
if (t != null) go = t.gameObject;
else
{
go = new GameObject(RootName);
go.transform.SetParent(robot, false);
}
if (go.GetComponent() == null) go.AddComponent();
RobotPathLine p = go.GetComponent();
if (p == null) p = go.AddComponent();
p.Setup(widthM);
return p;
}
void Setup(float widthM)
{
if (_line == null) _line = GetComponent();
_line.useWorldSpace = true; // 親が回っても線は曲がらない
_line.alignment = LineAlignment.View;
_line.textureMode = LineTextureMode.Stretch;
_line.numCapVertices = 2;
_line.numCornerVertices = 2;
_line.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off;
_line.receiveShadows = false;
_line.widthMultiplier = Mathf.Max(0.005f, widthM);
_line.positionCount = 0;
if (_line.sharedMaterial == null)
{
Shader s = Shader.Find("Universal Render Pipeline/Unlit");
if (s == null) s = Shader.Find("Sprites/Default");
if (s == null) s = Shader.Find("Unlit/Color");
if (s != null)
{
Material m = new Material(s);
m.name = "Mat_RobotPathLine";
_line.sharedMaterial = m;
}
}
}
///
/// 線を出し直す。points は道の曲がり角(世界の座標)。
/// carrying は料理を載せているか。heightM は床から浮かせる高さ。
///
public void Show(IReadOnlyList points, int fromIndex, Vector3 here,
bool carrying, float heightM)
{
if (_line == null) _line = GetComponent();
_points.Clear();
_points.Add(new Vector3(here.x, heightM, here.z));
if (points != null)
for (int i = Mathf.Max(0, fromIndex); i < points.Count; i++)
_points.Add(new Vector3(points[i].x, heightM, points[i].z));
if (_points.Count < 2)
{
_line.positionCount = 0;
return;
}
_line.positionCount = _points.Count;
for (int i = 0; i < _points.Count; i++) _line.SetPosition(i, _points[i]);
Color c = carrying ? CarryColor : EmptyColor;
_line.startColor = c;
_line.endColor = new Color(c.r, c.g, c.b, c.a * 0.35f);
if (_line.sharedMaterial != null && _line.sharedMaterial.HasProperty("_BaseColor"))
_line.sharedMaterial.SetColor("_BaseColor", c);
}
/// 線を消す
public void Hide()
{
if (_line == null) _line = GetComponent();
_line.positionCount = 0;
}
}
}