You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
225 lines
12 KiB
C#
225 lines
12 KiB
C#
using UnityEditor;
|
|
using UnityEditor.SceneManagement;
|
|
using UnityEngine;
|
|
using UnityEngine.UI;
|
|
using UnityEngine.Rendering;
|
|
|
|
namespace Class03.Editor
|
|
{
|
|
// 에디터에서 씬과 에셋을 만드는 도구입니다. 게임 실행에는 사용하지 않습니다.
|
|
public static class Class03SceneBuilder
|
|
{
|
|
private const string Root = "Assets/Class03";
|
|
|
|
[MenuItem("Class03/Create Scene")]
|
|
public static void CreateScene()
|
|
{
|
|
if (AssetDatabase.LoadAssetAtPath<SceneAsset>("Assets/Scenes/Class03.unity") != null)
|
|
throw new System.InvalidOperationException("Class03 scene already exists; refusing to overwrite it.");
|
|
if (!EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo()) return;
|
|
System.IO.Directory.CreateDirectory(Root + "/Materials");
|
|
System.IO.Directory.CreateDirectory(Root + "/Meshes");
|
|
System.IO.Directory.CreateDirectory(Root + "/Prefabs");
|
|
AssetDatabase.Refresh();
|
|
var scene = EditorSceneManager.NewScene(NewSceneSetup.EmptyScene, NewSceneMode.Single);
|
|
var floor = Material("Floor", new Color(0.065f, 0.12f, 0.20f), 0.15f, 0.25f);
|
|
var wall = Material("Walls", new Color(0.10f, 0.25f, 0.34f), 0.35f, 0.4f);
|
|
var cyan = Material("Cyan", new Color(0.12f, 0.85f, 0.94f), 0.25f, 0.6f);
|
|
var gold = Material("StarGold", new Color(1f, 0.67f, 0.08f), 0.55f, 0.65f);
|
|
var ballMat = Material("Ball", new Color(0.83f, 0.96f, 1f), 0.65f, 0.55f);
|
|
var grid = Material("Grid", new Color(0.12f, 0.22f, 0.31f), 0f, 0f);
|
|
var arena = new GameObject("Arena").transform;
|
|
Cube("Floor", new Vector3(0,-0.4f,0), new Vector3(20,0.8f,16), floor, arena);
|
|
Cube("Wall North", new Vector3(0,1,8), new Vector3(21,2,0.6f), wall, arena);
|
|
Cube("Wall South", new Vector3(0,1,-8), new Vector3(21,2,0.6f), wall, arena);
|
|
Cube("Wall East", new Vector3(10,1,0), new Vector3(0.6f,2,16), wall, arena);
|
|
Cube("Wall West", new Vector3(-10,1,0), new Vector3(0.6f,2,16), wall, arena);
|
|
Cube("North Light Strip", new Vector3(0,2.015f,8), new Vector3(20.6f,0.035f,0.12f), cyan, arena, false);
|
|
Cube("South Light Strip", new Vector3(0,2.015f,-8), new Vector3(20.6f,0.035f,0.12f), cyan, arena, false);
|
|
Cube("East Light Strip", new Vector3(10,2.015f,0), new Vector3(0.12f,0.035f,16), cyan, arena, false);
|
|
Cube("West Light Strip", new Vector3(-10,2.015f,0), new Vector3(0.12f,0.035f,16), cyan, arena, false);
|
|
var lines = new GameObject("Floor Grid").transform;
|
|
lines.SetParent(arena);
|
|
for (int x=-8;x<=8;x+=2) Cube("Grid X " + x,new Vector3(x,0.006f,0),new Vector3(0.018f,0.01f,15.4f),grid,lines,false);
|
|
for (int z=-6;z<=6;z+=2) Cube("Grid Z " + z,new Vector3(0,0.006f,z),new Vector3(19.4f,0.01f,0.018f),grid,lines,false);
|
|
|
|
var ball = GameObject.CreatePrimitive(PrimitiveType.Sphere);
|
|
ball.name = "Player Ball";
|
|
ball.transform.position = new Vector3(0,0.65f,-5.5f);
|
|
ball.transform.localScale = Vector3.one * 1.2f;
|
|
ball.GetComponent<Renderer>().sharedMaterial = ballMat;
|
|
var body = ball.AddComponent<Rigidbody>();
|
|
body.mass = 1f;
|
|
body.linearDamping = 1.25f;
|
|
body.angularDamping = 0.25f;
|
|
body.maxAngularVelocity = 20f;
|
|
body.interpolation = RigidbodyInterpolation.Interpolate;
|
|
body.collisionDetectionMode = CollisionDetectionMode.ContinuousDynamic;
|
|
ball.AddComponent<KeyboardMoveInput>();
|
|
ball.AddComponent<BallMotor>();
|
|
// 작은 표식이 공과 함께 회전하여 실제 구름을 알아보기 쉽게 합니다.
|
|
var marker = GameObject.CreatePrimitive(PrimitiveType.Sphere);
|
|
marker.name = "Rolling Marker";
|
|
Object.DestroyImmediate(marker.GetComponent<Collider>());
|
|
marker.transform.SetParent(ball.transform,false);
|
|
marker.transform.localPosition = new Vector3(0,0.44f,0);
|
|
marker.transform.localScale = new Vector3(0.3f,0.15f,0.3f);
|
|
marker.GetComponent<Renderer>().sharedMaterial = cyan;
|
|
|
|
var counter = new GameObject("Score Counter").AddComponent<ScoreCounter>();
|
|
Mesh mesh = StarMesh();
|
|
AssetDatabase.CreateAsset(mesh,Root + "/Meshes/Star.asset");
|
|
var star = new GameObject("Star");
|
|
var trigger = star.AddComponent<SphereCollider>();
|
|
trigger.radius = 0.7f;
|
|
trigger.isTrigger = true;
|
|
star.AddComponent<StarPickup>();
|
|
var visual = new GameObject("Visual");
|
|
visual.transform.SetParent(star.transform,false);
|
|
visual.AddComponent<MeshFilter>().sharedMesh = mesh;
|
|
visual.AddComponent<MeshRenderer>().sharedMaterial = gold;
|
|
visual.AddComponent<StarMotion>();
|
|
var prefab = PrefabUtility.SaveAsPrefabAsset(star,Root + "/Prefabs/Star.prefab");
|
|
Object.DestroyImmediate(star);
|
|
var stars = new GameObject("Stars").transform;
|
|
Vector3[] positions = {
|
|
new Vector3(-7,0.9f,-4.5f), new Vector3(-3.5f,0.9f,-1.5f),
|
|
new Vector3(-7,0.9f,3.5f), new Vector3(-2.5f,0.9f,5),
|
|
new Vector3(2.5f,0.9f,5), new Vector3(7,0.9f,3.5f),
|
|
new Vector3(3.5f,0.9f,-1.5f), new Vector3(7,0.9f,-4.5f)
|
|
};
|
|
for(int i=0;i<positions.Length;i++)
|
|
{
|
|
var instance=(GameObject)PrefabUtility.InstantiatePrefab(prefab);
|
|
instance.name="Star " + (i+1).ToString("00");
|
|
instance.transform.SetParent(stars);
|
|
instance.transform.position=positions[i];
|
|
instance.GetComponent<StarPickup>().Initialize(counter);
|
|
PrefabUtility.RecordPrefabInstancePropertyModifications(instance.GetComponent<StarPickup>());
|
|
var motion = new SerializedObject(instance.GetComponentInChildren<StarMotion>());
|
|
motion.FindProperty("phase").floatValue=i*0.65f;
|
|
motion.ApplyModifiedPropertiesWithoutUndo();
|
|
}
|
|
|
|
var camera = new GameObject("Main Camera").AddComponent<Camera>();
|
|
camera.tag="MainCamera";
|
|
camera.transform.position=new Vector3(0,22,-20);
|
|
camera.transform.LookAt(new Vector3(0,0,0));
|
|
camera.orthographic=true;
|
|
camera.orthographicSize=11f;
|
|
camera.clearFlags=CameraClearFlags.SolidColor;
|
|
camera.backgroundColor=new Color(0.018f,0.035f,0.065f);
|
|
camera.nearClipPlane=0.1f;
|
|
camera.farClipPlane=100f;
|
|
camera.gameObject.AddComponent<AudioListener>();
|
|
var light=new GameObject("Directional Light").AddComponent<Light>();
|
|
light.type=LightType.Directional;
|
|
light.intensity=1.5f;
|
|
light.shadows=LightShadows.Soft;
|
|
light.transform.rotation=Quaternion.Euler(45,-30,0);
|
|
RenderSettings.ambientMode=AmbientMode.Flat;
|
|
RenderSettings.ambientLight=new Color(0.48f,0.58f,0.72f);
|
|
CreateUI(counter);
|
|
EditorSceneManager.SaveScene(scene,"Assets/Scenes/Class03.unity");
|
|
AssetDatabase.SaveAssets();
|
|
Selection.activeGameObject=ball;
|
|
Debug.Log("Class03 created: ball, 8 stars, 4 walls and score UI.");
|
|
}
|
|
|
|
private static Material Material(string name,Color color,float metallic,float smoothness)
|
|
{
|
|
Shader shader=Shader.Find("Universal Render Pipeline/Lit");
|
|
if(shader==null) throw new System.InvalidOperationException("URP Lit shader missing.");
|
|
var material=new Material(shader){name=name};
|
|
material.SetColor("_BaseColor",color);
|
|
material.SetFloat("_Metallic",metallic);
|
|
material.SetFloat("_Smoothness",smoothness);
|
|
AssetDatabase.CreateAsset(material,Root + "/Materials/" + name + ".mat");
|
|
return material;
|
|
}
|
|
|
|
private static void Cube(string name,Vector3 position,Vector3 scale,Material material,Transform parent,bool solid=true)
|
|
{
|
|
var go=GameObject.CreatePrimitive(PrimitiveType.Cube);
|
|
go.name=name;
|
|
go.transform.SetParent(parent);
|
|
go.transform.position=position;
|
|
go.transform.localScale=scale;
|
|
go.GetComponent<Renderer>().sharedMaterial=material;
|
|
if(!solid) Object.DestroyImmediate(go.GetComponent<Collider>());
|
|
}
|
|
|
|
private static Mesh StarMesh()
|
|
{
|
|
var vertices=new Vector3[22];
|
|
vertices[0]=new Vector3(0,0,-0.16f);
|
|
vertices[11]=new Vector3(0,0,0.16f);
|
|
for(int i=0;i<10;i++)
|
|
{
|
|
float angle=(90+i*36)*Mathf.Deg2Rad;
|
|
float radius=i%2==0?0.65f:0.30f;
|
|
vertices[i+1]=new Vector3(Mathf.Cos(angle)*radius,Mathf.Sin(angle)*radius,-0.16f);
|
|
vertices[i+12]=new Vector3(Mathf.Cos(angle)*radius,Mathf.Sin(angle)*radius,0.16f);
|
|
}
|
|
var triangles=new System.Collections.Generic.List<int>();
|
|
for(int i=0;i<10;i++)
|
|
{
|
|
int a=i+1,b=(i+1)%10+1;
|
|
triangles.AddRange(new[]{0,b,a,11,a+11,b+11,a,b,b+11,a,b+11,a+11});
|
|
}
|
|
var mesh=new Mesh{name="Extruded Five Point Star",vertices=vertices,triangles=triangles.ToArray()};
|
|
mesh.RecalculateNormals();
|
|
mesh.RecalculateBounds();
|
|
return mesh;
|
|
}
|
|
|
|
private static void CreateUI(ScoreCounter counter)
|
|
{
|
|
var canvas=new GameObject("HUD",typeof(Canvas),typeof(CanvasScaler));
|
|
canvas.GetComponent<Canvas>().renderMode=RenderMode.ScreenSpaceOverlay;
|
|
var scaler=canvas.GetComponent<CanvasScaler>();
|
|
scaler.uiScaleMode=CanvasScaler.ScaleMode.ScaleWithScreenSize;
|
|
scaler.referenceResolution=new Vector2(1600,900);
|
|
scaler.matchWidthOrHeight=0.5f;
|
|
var panel=new GameObject("Score Panel",typeof(RectTransform),typeof(Image));
|
|
panel.transform.SetParent(canvas.transform,false);
|
|
var rect=panel.GetComponent<RectTransform>();
|
|
rect.anchorMin=rect.anchorMax=new Vector2(0,1);
|
|
rect.pivot=new Vector2(0,1);
|
|
rect.anchoredPosition=new Vector2(32,-32);
|
|
rect.sizeDelta=new Vector2(360,132);
|
|
panel.GetComponent<Image>().color=new Color(0.035f,0.07f,0.12f,0.96f);
|
|
TextLabel("Chapter",panel.transform,"CLASS 03 / STAR ROLL",new Vector2(22,-16),new Vector2(320,24),16,new Color(0.25f,0.85f,0.95f));
|
|
var score=TextLabel("Score",panel.transform,"STARS 00 / 08",new Vector2(20,-46),new Vector2(320,52),36,Color.white);
|
|
var status=TextLabel("Status",panel.transform,"ROLL. EXPLORE. COLLECT.",new Vector2(22,-103),new Vector2(320,22),15,new Color(1,0.75f,0.25f));
|
|
var help=TextLabel("Controls",canvas.transform,"W A S D / ARROW KEYS • COLLECT ALL 8 STARS",Vector2.zero,new Vector2(900,44),20,new Color(0.68f,0.80f,0.9f));
|
|
var helpRect=help.rectTransform;
|
|
helpRect.anchorMin=helpRect.anchorMax=new Vector2(0.5f,0);
|
|
helpRect.pivot=new Vector2(0.5f,0);
|
|
helpRect.anchoredPosition=new Vector2(0,22);
|
|
help.alignment=TextAnchor.MiddleCenter;
|
|
canvas.AddComponent<ScoreView>().Initialize(counter,score,status);
|
|
}
|
|
|
|
private static Text TextLabel(string name,Transform parent,string content,Vector2 position,Vector2 size,int fontSize,Color color)
|
|
{
|
|
var go=new GameObject(name,typeof(RectTransform),typeof(Text));
|
|
go.transform.SetParent(parent,false);
|
|
var text=go.GetComponent<Text>();
|
|
text.font=Resources.GetBuiltinResource<Font>("LegacyRuntime.ttf");
|
|
text.text=content;
|
|
text.fontSize=fontSize;
|
|
text.color=color;
|
|
text.raycastTarget=false;
|
|
text.fontStyle=FontStyle.Bold;
|
|
text.alignment=TextAnchor.MiddleLeft;
|
|
var rect=text.rectTransform;
|
|
rect.anchorMin=rect.anchorMax=new Vector2(0,1);
|
|
rect.pivot=new Vector2(0,1);
|
|
rect.anchoredPosition=position;
|
|
rect.sizeDelta=size;
|
|
return text;
|
|
}
|
|
}
|
|
}
|