feat: establish mech extraction prototype with bilingual UI
Track Unity source, scenes, editable assets, licenses, tools and QA evidence. Exclude generated caches, Windows builds and raw runtime logs.
This commit is contained in:
@@ -0,0 +1,121 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Ironspore
|
||||
{
|
||||
public static class WorldFactory
|
||||
{
|
||||
static readonly Dictionary<string, Material> materials = new Dictionary<string, Material>();
|
||||
public static Material Material(Color color, bool glow = false)
|
||||
{
|
||||
string key = ColorUtility.ToHtmlStringRGB(color) + (glow ? "g" : "");
|
||||
if (materials.TryGetValue(key, out var cached) && cached)
|
||||
return cached;
|
||||
var mat = new Material(Shader.Find("Standard"));
|
||||
mat.color = color;
|
||||
mat.SetFloat("_Metallic", .3f);
|
||||
mat.SetFloat("_Glossiness", .35f);
|
||||
if (glow)
|
||||
{
|
||||
mat.EnableKeyword("_EMISSION");
|
||||
mat.SetColor("_EmissionColor", color * 1.8f);
|
||||
}
|
||||
materials[key] = mat;
|
||||
return mat;
|
||||
}
|
||||
public static GameObject Box(string name, Vector3 position, Vector3 scale, Color color, Transform parent, bool collision = true, bool glow = false)
|
||||
{
|
||||
return Primitive(PrimitiveType.Cube, name, position, scale, color, parent, collision, glow);
|
||||
}
|
||||
public static GameObject Cylinder(string name, Vector3 position, Vector3 scale, Color color, Transform parent, bool collision = true)
|
||||
{
|
||||
return Primitive(PrimitiveType.Cylinder, name, position, scale, color, parent, collision, false);
|
||||
}
|
||||
public static GameObject Primitive(PrimitiveType type, string name, Vector3 position, Vector3 scale, Color color, Transform parent, bool collision, bool glow)
|
||||
{
|
||||
var obj = GameObject.CreatePrimitive(type);
|
||||
obj.name = name;
|
||||
obj.transform.SetParent(parent);
|
||||
obj.transform.position = position;
|
||||
obj.transform.localScale = scale;
|
||||
obj.GetComponent<Renderer>().sharedMaterial = Material(color, glow);
|
||||
if (!collision)
|
||||
Object.Destroy(obj.GetComponent<Collider>());
|
||||
return obj;
|
||||
}
|
||||
public static GameObject Cockpit(Transform camera)
|
||||
{
|
||||
var root = new GameObject("CockpitFrame");
|
||||
root.transform.SetParent(camera, false);
|
||||
foreach (int side in new[] { -1, 1 })
|
||||
{
|
||||
var frame = Box("CanopyRail", Vector3.zero, new Vector3(.045f, .8f, .06f), new Color(.08f, .16f, .19f), root.transform, false);
|
||||
frame.transform.localPosition = new Vector3(side * .48f, -.05f, .7f);
|
||||
frame.transform.localRotation = Quaternion.Euler(0, 0, side * -12);
|
||||
var indicator = Box("CanopyIndicator", Vector3.zero, new Vector3(.018f, .27f, .065f), new Color(.05f, .9f, .75f), root.transform, false, true);
|
||||
indicator.transform.localPosition = new Vector3(side * .48f, -.15f, .66f);
|
||||
}
|
||||
var dashboard = Box("Dashboard", Vector3.zero, new Vector3(1.3f, .14f, .2f), new Color(.07f, .13f, .16f), root.transform, false);
|
||||
dashboard.transform.localPosition = new Vector3(0, -.42f, .75f);
|
||||
foreach (var child in root.GetComponentsInChildren<Transform>())
|
||||
child.gameObject.layer = 8;
|
||||
root.SetActive(false);
|
||||
return root;
|
||||
}
|
||||
public static void Label(string key, Vector3 position, Color color, Transform parent)
|
||||
{
|
||||
var obj = new GameObject("Sign");
|
||||
obj.transform.SetParent(parent);
|
||||
obj.transform.position = position;
|
||||
var label = obj.AddComponent<TextMesh>();
|
||||
label.fontSize = 40;
|
||||
label.characterSize = .09f;
|
||||
label.anchor = TextAnchor.MiddleCenter;
|
||||
label.color = color;
|
||||
obj.AddComponent<LocalizedWorldLabel>().Initialize(key);
|
||||
obj.AddComponent<FaceCamera>();
|
||||
}
|
||||
public static void Tracer(Vector3 from, Vector3 to, Color color)
|
||||
{
|
||||
var obj = new GameObject("ShotTrace");
|
||||
var line = obj.AddComponent<LineRenderer>();
|
||||
line.positionCount = 2;
|
||||
line.SetPosition(0, from);
|
||||
line.SetPosition(1, to);
|
||||
line.startWidth = .045f;
|
||||
line.endWidth = .015f;
|
||||
line.sharedMaterial = Material(color, true);
|
||||
Object.Destroy(obj, .07f);
|
||||
}
|
||||
}
|
||||
public sealed class FaceCamera : MonoBehaviour
|
||||
{
|
||||
void LateUpdate()
|
||||
{
|
||||
var c = Camera.main;
|
||||
if (!c)
|
||||
c = Object.FindAnyObjectByType<Camera>();
|
||||
if (c)
|
||||
transform.rotation = c.transform.rotation;
|
||||
}
|
||||
}
|
||||
public static class GameAudio
|
||||
{
|
||||
public static void Cue(float frequency, float length, float volume = .12f)
|
||||
{
|
||||
int count = (int)(22050 * length);
|
||||
var data = new float[count];
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
float t = i / 22050f;
|
||||
data[i] = Mathf.Sin(t * frequency * Mathf.PI * 2) * Mathf.Exp(-t / length * 6);
|
||||
}
|
||||
var clip = AudioClip.Create("SynthCue", count, 1, 22050, false);
|
||||
clip.SetData(data, 0);
|
||||
var camera = Object.FindAnyObjectByType<AudioListener>();
|
||||
if (camera)
|
||||
AudioSource.PlayClipAtPoint(clip, camera.transform.position, volume);
|
||||
Object.Destroy(clip, length + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user