861 lines
39 KiB
C#
861 lines
39 KiB
C#
|
|
using System.Collections.Generic;
|
||
|
|
using System.IO;
|
||
|
|
using OTG.Lab06.Abilities;
|
||
|
|
using OTG.Lab06.Characters;
|
||
|
|
using OTG.Lab06.Combat;
|
||
|
|
using OTG.Lab06.Effects;
|
||
|
|
using OTG.Lab06.UI;
|
||
|
|
using UnityEditor;
|
||
|
|
using UnityEditor.SceneManagement;
|
||
|
|
using UnityEngine;
|
||
|
|
using UnityEngine.EventSystems;
|
||
|
|
using UnityEngine.SceneManagement;
|
||
|
|
using UnityEngine.UI;
|
||
|
|
|
||
|
|
public static class Lab6SceneBuilder
|
||
|
|
{
|
||
|
|
private const string Root = "Assets";
|
||
|
|
private const string ScenePath = "Assets/_Scenes/Lab06_AbilitySystem.unity";
|
||
|
|
private const string FontFilePath = "Assets/_Fonts/Ubuntu-R.ttf";
|
||
|
|
|
||
|
|
[MenuItem("Tools/Technical Game Design/Lab6/Create Ability System Scene")]
|
||
|
|
public static void CreateAbilitySystemScene()
|
||
|
|
{
|
||
|
|
CreateProjectStructure();
|
||
|
|
Font font = CopyUbuntuFont();
|
||
|
|
Dictionary<string, Material> materials = CreateMaterials();
|
||
|
|
Dictionary<string, Sprite> icons = CreateIcons();
|
||
|
|
|
||
|
|
GameObject deathEffect = CreateDeathEffectPrefab(materials["ArcaneViolet"]);
|
||
|
|
FloatingDamage floatingDamage = CreateFloatingDamagePrefab(font);
|
||
|
|
GameObject fireballEffect = CreateFireballPrefab(materials["Fire"], materials["FireTrail"]);
|
||
|
|
GameObject iceNovaEffect = CreateIceNovaPrefab(materials["Ice"]);
|
||
|
|
GameObject blinkEffect = CreateBlinkPrefab(materials["Blink"]);
|
||
|
|
|
||
|
|
AbilityData fireball = CreateAbility("Fireball", "fireball", "Launches a burning projectile that detonates on the first enemy hit.", 8f, 2f, 30f, 24f, icons["Fireball"], fireballEffect);
|
||
|
|
AbilityData iceNova = CreateAbility("Ice Nova", "ice_nova", "Releases a sharp frost ring that damages all nearby enemies.", 14f, 5f, 20f, 5.5f, icons["IceNova"], iceNovaEffect);
|
||
|
|
AbilityData blink = CreateAbility("Blink", "blink", "Teleports forward and stops safely before obstacles.", 10f, 6f, 0f, 8f, icons["Blink"], blinkEffect);
|
||
|
|
|
||
|
|
GameObject enemyPrefab = CreateEnemyPrefab(materials["Enemy"], deathEffect);
|
||
|
|
GameObject crystalPrefab = CreateManaCrystalPrefab(materials["ManaCrystal"]);
|
||
|
|
AbilitySlotUI slotPrefab = CreateAbilitySlotPrefab(font, materials);
|
||
|
|
|
||
|
|
Scene scene = EditorSceneManager.NewScene(NewSceneSetup.EmptyScene, NewSceneMode.Single);
|
||
|
|
scene.name = "Lab06_AbilitySystem";
|
||
|
|
|
||
|
|
BuildLighting();
|
||
|
|
BuildArena(materials);
|
||
|
|
GameObject player = BuildPlayer(materials, fireball, iceNova, blink);
|
||
|
|
BuildCamera(player.transform);
|
||
|
|
BuildEnemies(enemyPrefab);
|
||
|
|
BuildTrainingMannequins(materials);
|
||
|
|
BuildManaCrystals(crystalPrefab);
|
||
|
|
BuildFloatingDamageManager(floatingDamage);
|
||
|
|
BuildUI(player, slotPrefab, font, materials);
|
||
|
|
|
||
|
|
EditorSceneManager.SaveScene(scene, ScenePath);
|
||
|
|
AssetDatabase.SaveAssets();
|
||
|
|
AssetDatabase.Refresh();
|
||
|
|
EditorUtility.DisplayDialog("Lab06", "Ability System scene has been generated.", "OK");
|
||
|
|
}
|
||
|
|
|
||
|
|
private static void CreateProjectStructure()
|
||
|
|
{
|
||
|
|
string[] folders =
|
||
|
|
{
|
||
|
|
"_Scenes", "_Scripts", "_Scripts/Core", "_Scripts/Abilities", "_Scripts/Combat",
|
||
|
|
"_Scripts/Characters", "_Scripts/UI", "_Scripts/Effects", "_Data", "_Data/Abilities",
|
||
|
|
"_Prefabs", "_Prefabs/Abilities", "_Prefabs/UI", "_Prefabs/Enemies", "_Materials", "_Fonts", "Editor"
|
||
|
|
};
|
||
|
|
|
||
|
|
foreach (string folder in folders)
|
||
|
|
{
|
||
|
|
string path = $"{Root}/{folder}";
|
||
|
|
if (!AssetDatabase.IsValidFolder(path))
|
||
|
|
{
|
||
|
|
string parent = Path.GetDirectoryName(path).Replace('\\', '/');
|
||
|
|
string name = Path.GetFileName(path);
|
||
|
|
AssetDatabase.CreateFolder(parent, name);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private static Font CopyUbuntuFont()
|
||
|
|
{
|
||
|
|
string[] candidates =
|
||
|
|
{
|
||
|
|
"/usr/share/fonts/truetype/ubuntu/Ubuntu-R.ttf",
|
||
|
|
"/usr/share/fonts/truetype/ubuntu/Ubuntu-M.ttf",
|
||
|
|
"/usr/share/fonts/TTF/Ubuntu-R.ttf"
|
||
|
|
};
|
||
|
|
|
||
|
|
string source = null;
|
||
|
|
foreach (string candidate in candidates)
|
||
|
|
{
|
||
|
|
if (File.Exists(candidate))
|
||
|
|
{
|
||
|
|
source = candidate;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (source == null)
|
||
|
|
{
|
||
|
|
throw new FileNotFoundException("Ubuntu font was not found in standard Linux font directories.");
|
||
|
|
}
|
||
|
|
|
||
|
|
File.Copy(source, FontFilePath, true);
|
||
|
|
AssetDatabase.ImportAsset(FontFilePath, ImportAssetOptions.ForceUpdate);
|
||
|
|
AssetDatabase.Refresh(ImportAssetOptions.ForceSynchronousImport);
|
||
|
|
|
||
|
|
Font font = AssetDatabase.LoadAssetAtPath<Font>(FontFilePath);
|
||
|
|
if (font == null)
|
||
|
|
{
|
||
|
|
throw new FileNotFoundException("Ubuntu font was copied but Unity could not import it as a Font asset.");
|
||
|
|
}
|
||
|
|
return font;
|
||
|
|
}
|
||
|
|
|
||
|
|
private static Dictionary<string, Material> CreateMaterials()
|
||
|
|
{
|
||
|
|
var result = new Dictionary<string, Material>
|
||
|
|
{
|
||
|
|
["ArenaFloor"] = CreateMaterial("ArenaFloor", new Color(0.48f, 0.49f, 0.46f), 0.08f),
|
||
|
|
["ArenaTrim"] = CreateMaterial("ArenaTrim", new Color(0.34f, 0.36f, 0.36f), 0.06f),
|
||
|
|
["ArenaWall"] = CreateMaterial("ArenaWall", new Color(0.42f, 0.43f, 0.41f), 0.05f),
|
||
|
|
["ArenaLine"] = CreateMaterial("ArenaLine", new Color(0.58f, 0.60f, 0.57f), 0.03f),
|
||
|
|
["Player"] = CreateMaterial("Player", new Color(0.12f, 0.39f, 0.82f), 0.25f),
|
||
|
|
["Enemy"] = CreateMaterial("Enemy", new Color(0.58f, 0.08f, 0.12f), 0.16f),
|
||
|
|
["Mannequin"] = CreateMaterial("Mannequin", new Color(0.56f, 0.43f, 0.28f), 0.05f),
|
||
|
|
["Fire"] = CreateMaterial("Fire", new Color(1f, 0.32f, 0.08f), 0.4f, new Color(2.2f, 0.55f, 0.08f)),
|
||
|
|
["FireTrail"] = CreateMaterial("FireTrail", new Color(1f, 0.68f, 0.12f, 0.55f), 0.15f, new Color(1.3f, 0.55f, 0.12f)),
|
||
|
|
["Ice"] = CreateMaterial("Ice", new Color(0.42f, 0.85f, 1f, 0.62f), 0.25f, new Color(0.2f, 0.9f, 1.7f)),
|
||
|
|
["Blink"] = CreateMaterial("Blink", new Color(0.52f, 0.48f, 1f, 0.66f), 0.3f, new Color(0.75f, 0.55f, 2.1f)),
|
||
|
|
["ManaCrystal"] = CreateMaterial("ManaCrystal", new Color(0.18f, 0.9f, 0.95f), 0.45f, new Color(0.05f, 1.4f, 1.8f)),
|
||
|
|
["ArcaneViolet"] = CreateMaterial("ArcaneViolet", new Color(0.58f, 0.23f, 0.86f), 0.35f, new Color(0.8f, 0.2f, 1.4f)),
|
||
|
|
["UIBack"] = CreateMaterial("UIBack", new Color(0.07f, 0.08f, 0.09f, 0.88f), 0f),
|
||
|
|
};
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
|
||
|
|
private static Material CreateMaterial(string name, Color color, float smoothness, Color? emission = null)
|
||
|
|
{
|
||
|
|
string path = $"Assets/_Materials/{name}.mat";
|
||
|
|
Material material = AssetDatabase.LoadAssetAtPath<Material>(path);
|
||
|
|
if (material == null)
|
||
|
|
{
|
||
|
|
material = new Material(Shader.Find("Standard"));
|
||
|
|
AssetDatabase.CreateAsset(material, path);
|
||
|
|
}
|
||
|
|
|
||
|
|
material.color = color;
|
||
|
|
material.SetFloat("_Glossiness", smoothness);
|
||
|
|
if (emission.HasValue)
|
||
|
|
{
|
||
|
|
material.EnableKeyword("_EMISSION");
|
||
|
|
material.SetColor("_EmissionColor", emission.Value);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
material.DisableKeyword("_EMISSION");
|
||
|
|
}
|
||
|
|
|
||
|
|
EditorUtility.SetDirty(material);
|
||
|
|
return material;
|
||
|
|
}
|
||
|
|
|
||
|
|
private static Dictionary<string, Sprite> CreateIcons()
|
||
|
|
{
|
||
|
|
return new Dictionary<string, Sprite>
|
||
|
|
{
|
||
|
|
["Fireball"] = CreateIcon("FireballIcon", new Color(0.95f, 0.22f, 0.07f), new Color(1f, 0.75f, 0.15f)),
|
||
|
|
["IceNova"] = CreateIcon("IceNovaIcon", new Color(0.1f, 0.55f, 0.95f), new Color(0.78f, 0.96f, 1f)),
|
||
|
|
["Blink"] = CreateIcon("BlinkIcon", new Color(0.35f, 0.2f, 0.85f), new Color(0.85f, 0.78f, 1f))
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
private static Sprite CreateIcon(string name, Color baseColor, Color markColor)
|
||
|
|
{
|
||
|
|
string pngPath = $"Assets/_Data/Abilities/{name}.png";
|
||
|
|
Texture2D texture = new Texture2D(64, 64, TextureFormat.RGBA32, false);
|
||
|
|
for (int y = 0; y < 64; y++)
|
||
|
|
{
|
||
|
|
for (int x = 0; x < 64; x++)
|
||
|
|
{
|
||
|
|
Vector2 p = new Vector2(x - 31.5f, y - 31.5f);
|
||
|
|
float ring = Mathf.InverseLerp(32f, 12f, p.magnitude);
|
||
|
|
Color color = Color.Lerp(new Color(0.04f, 0.05f, 0.06f, 1f), baseColor, Mathf.Clamp01(ring));
|
||
|
|
if (Mathf.Abs(p.x) < 5f || Mathf.Abs(p.y) < 5f || p.magnitude < 12f)
|
||
|
|
{
|
||
|
|
color = Color.Lerp(color, markColor, 0.75f);
|
||
|
|
}
|
||
|
|
texture.SetPixel(x, y, color);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
texture.Apply();
|
||
|
|
File.WriteAllBytes(pngPath, texture.EncodeToPNG());
|
||
|
|
Object.DestroyImmediate(texture);
|
||
|
|
AssetDatabase.ImportAsset(pngPath, ImportAssetOptions.ForceUpdate);
|
||
|
|
|
||
|
|
TextureImporter importer = (TextureImporter)AssetImporter.GetAtPath(pngPath);
|
||
|
|
importer.textureType = TextureImporterType.Sprite;
|
||
|
|
importer.spritePixelsPerUnit = 64f;
|
||
|
|
importer.mipmapEnabled = false;
|
||
|
|
importer.SaveAndReimport();
|
||
|
|
return AssetDatabase.LoadAssetAtPath<Sprite>(pngPath);
|
||
|
|
}
|
||
|
|
|
||
|
|
private static AbilityData CreateAbility(string displayName, string id, string description, float mana, float cooldown, float damage, float range, Sprite icon, GameObject effectPrefab)
|
||
|
|
{
|
||
|
|
string path = $"Assets/_Data/Abilities/{displayName.Replace(" ", string.Empty)}.asset";
|
||
|
|
AbilityData data = AssetDatabase.LoadAssetAtPath<AbilityData>(path);
|
||
|
|
if (data == null)
|
||
|
|
{
|
||
|
|
data = ScriptableObject.CreateInstance<AbilityData>();
|
||
|
|
AssetDatabase.CreateAsset(data, path);
|
||
|
|
}
|
||
|
|
|
||
|
|
data.abilityId = id;
|
||
|
|
data.abilityName = displayName;
|
||
|
|
data.description = description;
|
||
|
|
data.icon = icon;
|
||
|
|
data.manaCost = mana;
|
||
|
|
data.cooldown = cooldown;
|
||
|
|
data.damage = damage;
|
||
|
|
data.castRange = range;
|
||
|
|
data.effectPrefab = effectPrefab;
|
||
|
|
EditorUtility.SetDirty(data);
|
||
|
|
return data;
|
||
|
|
}
|
||
|
|
|
||
|
|
private static GameObject CreateFireballPrefab(Material fire, Material trail)
|
||
|
|
{
|
||
|
|
GameObject root = new GameObject("PF_FireballEffect");
|
||
|
|
var collider = root.AddComponent<SphereCollider>();
|
||
|
|
collider.radius = 0.35f;
|
||
|
|
collider.isTrigger = true;
|
||
|
|
root.AddComponent<FireballEffect>();
|
||
|
|
|
||
|
|
GameObject visual = GameObject.CreatePrimitive(PrimitiveType.Sphere);
|
||
|
|
visual.name = "Fireball_Visual";
|
||
|
|
visual.transform.SetParent(root.transform, false);
|
||
|
|
visual.transform.localScale = Vector3.one * 0.55f;
|
||
|
|
Object.DestroyImmediate(visual.GetComponent<Collider>());
|
||
|
|
visual.GetComponent<Renderer>().sharedMaterial = fire;
|
||
|
|
|
||
|
|
ParticleSystem particles = root.AddComponent<ParticleSystem>();
|
||
|
|
ParticleSystem.MainModule main = particles.main;
|
||
|
|
main.startLifetime = 0.35f;
|
||
|
|
main.startSpeed = 0.2f;
|
||
|
|
main.startSize = 0.32f;
|
||
|
|
main.startColor = new Color(1f, 0.42f, 0.05f, 0.7f);
|
||
|
|
ParticleSystem.EmissionModule emission = particles.emission;
|
||
|
|
emission.rateOverTime = 34f;
|
||
|
|
ParticleSystemRenderer renderer = particles.GetComponent<ParticleSystemRenderer>();
|
||
|
|
renderer.sharedMaterial = trail;
|
||
|
|
|
||
|
|
return SavePrefab(root, "Assets/_Prefabs/Abilities/PF_FireballEffect.prefab");
|
||
|
|
}
|
||
|
|
|
||
|
|
private static GameObject CreateIceNovaPrefab(Material material)
|
||
|
|
{
|
||
|
|
GameObject root = new GameObject("PF_IceNovaEffect");
|
||
|
|
root.AddComponent<IceNovaEffect>();
|
||
|
|
|
||
|
|
GameObject ring = GameObject.CreatePrimitive(PrimitiveType.Cylinder);
|
||
|
|
ring.name = "IceNova_Ring";
|
||
|
|
ring.transform.SetParent(root.transform, false);
|
||
|
|
ring.transform.localScale = new Vector3(5.5f, 0.035f, 5.5f);
|
||
|
|
Object.DestroyImmediate(ring.GetComponent<Collider>());
|
||
|
|
ring.GetComponent<Renderer>().sharedMaterial = material;
|
||
|
|
|
||
|
|
ParticleSystem particles = root.AddComponent<ParticleSystem>();
|
||
|
|
ParticleSystem.MainModule main = particles.main;
|
||
|
|
main.startLifetime = 0.7f;
|
||
|
|
main.startSpeed = 2.1f;
|
||
|
|
main.startSize = 0.18f;
|
||
|
|
main.startColor = new Color(0.55f, 0.9f, 1f, 0.75f);
|
||
|
|
ParticleSystem.ShapeModule shape = particles.shape;
|
||
|
|
shape.shapeType = ParticleSystemShapeType.Circle;
|
||
|
|
shape.radius = 5.4f;
|
||
|
|
ParticleSystem.EmissionModule emission = particles.emission;
|
||
|
|
emission.rateOverTime = 90f;
|
||
|
|
|
||
|
|
return SavePrefab(root, "Assets/_Prefabs/Abilities/PF_IceNovaEffect.prefab");
|
||
|
|
}
|
||
|
|
|
||
|
|
private static GameObject CreateBlinkPrefab(Material material)
|
||
|
|
{
|
||
|
|
GameObject root = new GameObject("PF_BlinkEffect");
|
||
|
|
root.AddComponent<BlinkEffect>();
|
||
|
|
|
||
|
|
GameObject burst = GameObject.CreatePrimitive(PrimitiveType.Cylinder);
|
||
|
|
burst.name = "Blink_Burst";
|
||
|
|
burst.transform.SetParent(root.transform, false);
|
||
|
|
burst.transform.localScale = new Vector3(1.25f, 0.05f, 1.25f);
|
||
|
|
Object.DestroyImmediate(burst.GetComponent<Collider>());
|
||
|
|
burst.GetComponent<Renderer>().sharedMaterial = material;
|
||
|
|
|
||
|
|
ParticleSystem particles = root.AddComponent<ParticleSystem>();
|
||
|
|
ParticleSystem.MainModule main = particles.main;
|
||
|
|
main.startLifetime = 0.45f;
|
||
|
|
main.startSpeed = 1.4f;
|
||
|
|
main.startSize = 0.22f;
|
||
|
|
main.startColor = new Color(0.65f, 0.55f, 1f, 0.8f);
|
||
|
|
ParticleSystem.EmissionModule emission = particles.emission;
|
||
|
|
emission.rateOverTime = 70f;
|
||
|
|
|
||
|
|
return SavePrefab(root, "Assets/_Prefabs/Abilities/PF_BlinkEffect.prefab");
|
||
|
|
}
|
||
|
|
|
||
|
|
private static GameObject CreateDeathEffectPrefab(Material material)
|
||
|
|
{
|
||
|
|
GameObject root = new GameObject("PF_EnemyDeathEffect");
|
||
|
|
ParticleSystem particles = root.AddComponent<ParticleSystem>();
|
||
|
|
ParticleSystem.MainModule main = particles.main;
|
||
|
|
main.startLifetime = 0.65f;
|
||
|
|
main.startSpeed = 1.8f;
|
||
|
|
main.startSize = 0.22f;
|
||
|
|
main.duration = 0.5f;
|
||
|
|
main.loop = false;
|
||
|
|
main.startColor = new Color(0.65f, 0.2f, 1f, 0.85f);
|
||
|
|
ParticleSystem.EmissionModule emission = particles.emission;
|
||
|
|
emission.rateOverTime = 0f;
|
||
|
|
emission.SetBursts(new[] { new ParticleSystem.Burst(0f, 34) });
|
||
|
|
particles.GetComponent<ParticleSystemRenderer>().sharedMaterial = material;
|
||
|
|
var destroy = root.AddComponent<SelfDestruct>();
|
||
|
|
SetFloat(destroy, "lifetime", 1.2f);
|
||
|
|
return SavePrefab(root, "Assets/_Prefabs/Abilities/PF_EnemyDeathEffect.prefab");
|
||
|
|
}
|
||
|
|
|
||
|
|
private static FloatingDamage CreateFloatingDamagePrefab(Font font)
|
||
|
|
{
|
||
|
|
GameObject root = new GameObject("PF_FloatingDamage");
|
||
|
|
Canvas canvas = root.AddComponent<Canvas>();
|
||
|
|
canvas.renderMode = RenderMode.WorldSpace;
|
||
|
|
RectTransform canvasRect = root.GetComponent<RectTransform>();
|
||
|
|
canvasRect.sizeDelta = new Vector2(120f, 48f);
|
||
|
|
canvasRect.localScale = Vector3.one * 0.01f;
|
||
|
|
|
||
|
|
GameObject labelObject = new GameObject("DamageLabel", typeof(RectTransform));
|
||
|
|
labelObject.transform.SetParent(root.transform, false);
|
||
|
|
Text label = labelObject.AddComponent<Text>();
|
||
|
|
label.font = font;
|
||
|
|
label.fontSize = 38;
|
||
|
|
label.alignment = TextAnchor.MiddleCenter;
|
||
|
|
label.color = new Color(1f, 0.86f, 0.28f, 1f);
|
||
|
|
Stretch(label.rectTransform);
|
||
|
|
|
||
|
|
FloatingDamage damage = root.AddComponent<FloatingDamage>();
|
||
|
|
SetObject(damage, "label", label);
|
||
|
|
GameObject prefab = SavePrefab(root, "Assets/_Prefabs/UI/PF_FloatingDamage.prefab");
|
||
|
|
return prefab.GetComponent<FloatingDamage>();
|
||
|
|
}
|
||
|
|
|
||
|
|
private static GameObject CreateEnemyPrefab(Material enemyMaterial, GameObject deathEffect)
|
||
|
|
{
|
||
|
|
GameObject root = GameObject.CreatePrimitive(PrimitiveType.Capsule);
|
||
|
|
root.name = "PF_Enemy";
|
||
|
|
root.transform.localScale = new Vector3(1f, 1.35f, 1f);
|
||
|
|
root.GetComponent<Renderer>().sharedMaterial = enemyMaterial;
|
||
|
|
CapsuleCollider hitbox = root.GetComponent<CapsuleCollider>();
|
||
|
|
hitbox.radius = 0.85f;
|
||
|
|
hitbox.height = 2.4f;
|
||
|
|
Enemy enemy = root.AddComponent<Enemy>();
|
||
|
|
SetObject(enemy, "deathEffectPrefab", deathEffect);
|
||
|
|
return SavePrefab(root, "Assets/_Prefabs/Enemies/PF_Enemy.prefab");
|
||
|
|
}
|
||
|
|
|
||
|
|
private static GameObject CreateManaCrystalPrefab(Material material)
|
||
|
|
{
|
||
|
|
GameObject root = new GameObject("PF_ManaCrystal");
|
||
|
|
SphereCollider trigger = root.AddComponent<SphereCollider>();
|
||
|
|
trigger.isTrigger = true;
|
||
|
|
trigger.radius = 1.2f;
|
||
|
|
|
||
|
|
GameObject visual = GameObject.CreatePrimitive(PrimitiveType.Sphere);
|
||
|
|
visual.name = "CrystalVisual";
|
||
|
|
visual.transform.SetParent(root.transform, false);
|
||
|
|
visual.transform.localPosition = Vector3.up * 0.8f;
|
||
|
|
visual.transform.localScale = new Vector3(0.65f, 1.25f, 0.65f);
|
||
|
|
Object.DestroyImmediate(visual.GetComponent<Collider>());
|
||
|
|
visual.GetComponent<Renderer>().sharedMaterial = material;
|
||
|
|
|
||
|
|
ManaCrystal crystal = root.AddComponent<ManaCrystal>();
|
||
|
|
SetObject(crystal, "visualRoot", visual);
|
||
|
|
return SavePrefab(root, "Assets/_Prefabs/Abilities/PF_ManaCrystal.prefab");
|
||
|
|
}
|
||
|
|
|
||
|
|
private static AbilitySlotUI CreateAbilitySlotPrefab(Font font, Dictionary<string, Material> materials)
|
||
|
|
{
|
||
|
|
GameObject root = CreateUIObject("PF_AbilitySlot", null, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(76f, 76f), Vector2.zero);
|
||
|
|
Image back = root.AddComponent<Image>();
|
||
|
|
back.color = new Color(0.045f, 0.05f, 0.055f, 0.9f);
|
||
|
|
|
||
|
|
GameObject iconObject = CreateUIObject("Icon", root.transform, Vector2.zero, Vector2.one, new Vector2(0.5f, 0.5f), new Vector2(-14f, -22f), new Vector2(0f, 8f));
|
||
|
|
Image icon = iconObject.AddComponent<Image>();
|
||
|
|
icon.preserveAspect = true;
|
||
|
|
icon.raycastTarget = false;
|
||
|
|
|
||
|
|
GameObject overlayObject = CreateUIObject("CooldownOverlay", root.transform, Vector2.zero, Vector2.one, new Vector2(0.5f, 0.5f), new Vector2(-14f, -22f), new Vector2(0f, 8f));
|
||
|
|
Image overlay = overlayObject.AddComponent<Image>();
|
||
|
|
overlay.color = new Color(0f, 0f, 0f, 0.68f);
|
||
|
|
overlay.type = Image.Type.Filled;
|
||
|
|
overlay.fillMethod = Image.FillMethod.Radial360;
|
||
|
|
overlay.fillOrigin = 2;
|
||
|
|
overlay.raycastTarget = false;
|
||
|
|
|
||
|
|
Text key = CreateText("Hotkey", root.transform, font, "1", 18, TextAnchor.MiddleCenter, new Color(0.95f, 0.95f, 0.95f, 1f));
|
||
|
|
Anchor(key.rectTransform, new Vector2(0f, 1f), new Vector2(0f, 1f), new Vector2(0f, 1f), new Vector2(22f, 22f), new Vector2(9f, -8f));
|
||
|
|
|
||
|
|
Text name = CreateText("Name", root.transform, font, "Fireball", 11, TextAnchor.MiddleCenter, new Color(0.88f, 0.91f, 0.94f, 1f));
|
||
|
|
Anchor(name.rectTransform, new Vector2(0f, 0f), new Vector2(1f, 0f), new Vector2(0.5f, 0f), new Vector2(-8f, 18f), new Vector2(0f, 10f));
|
||
|
|
|
||
|
|
Text mana = CreateText("Mana", root.transform, font, "15", 13, TextAnchor.MiddleRight, new Color(0.43f, 0.9f, 1f, 1f));
|
||
|
|
Anchor(mana.rectTransform, new Vector2(1f, 1f), new Vector2(1f, 1f), new Vector2(1f, 1f), new Vector2(34f, 20f), new Vector2(-7f, -8f));
|
||
|
|
|
||
|
|
Text cooldown = CreateText("Cooldown", root.transform, font, "", 20, TextAnchor.MiddleCenter, Color.white);
|
||
|
|
Stretch(cooldown.rectTransform);
|
||
|
|
|
||
|
|
AbilitySlotUI slot = root.AddComponent<AbilitySlotUI>();
|
||
|
|
SetObject(slot, "icon", icon);
|
||
|
|
SetObject(slot, "cooldownOverlay", overlay);
|
||
|
|
SetObject(slot, "hotkeyLabel", key);
|
||
|
|
SetObject(slot, "nameLabel", name);
|
||
|
|
SetObject(slot, "manaLabel", mana);
|
||
|
|
SetObject(slot, "cooldownLabel", cooldown);
|
||
|
|
|
||
|
|
GameObject prefab = SavePrefab(root, "Assets/_Prefabs/UI/PF_AbilitySlot.prefab");
|
||
|
|
return prefab.GetComponent<AbilitySlotUI>();
|
||
|
|
}
|
||
|
|
|
||
|
|
private static void BuildLighting()
|
||
|
|
{
|
||
|
|
RenderSettings.ambientLight = new Color(0.38f, 0.39f, 0.40f);
|
||
|
|
RenderSettings.fog = true;
|
||
|
|
RenderSettings.fogColor = new Color(0.58f, 0.62f, 0.65f);
|
||
|
|
RenderSettings.fogMode = FogMode.Linear;
|
||
|
|
RenderSettings.fogStartDistance = 35f;
|
||
|
|
RenderSettings.fogEndDistance = 80f;
|
||
|
|
|
||
|
|
GameObject lightObject = new GameObject("Directional Light");
|
||
|
|
Light light = lightObject.AddComponent<Light>();
|
||
|
|
light.type = LightType.Directional;
|
||
|
|
light.intensity = 1.05f;
|
||
|
|
lightObject.transform.rotation = Quaternion.Euler(55f, -38f, 0f);
|
||
|
|
|
||
|
|
GameObject rimObject = new GameObject("Arena Arcane Fill Light");
|
||
|
|
Light rim = rimObject.AddComponent<Light>();
|
||
|
|
rim.type = LightType.Point;
|
||
|
|
rim.intensity = 3.2f;
|
||
|
|
rim.range = 28f;
|
||
|
|
rim.color = new Color(0.36f, 0.7f, 1f);
|
||
|
|
rimObject.transform.position = new Vector3(0f, 8f, -8f);
|
||
|
|
}
|
||
|
|
|
||
|
|
private static void BuildArena(Dictionary<string, Material> materials)
|
||
|
|
{
|
||
|
|
const float arenaSize = 52f;
|
||
|
|
const float half = arenaSize * 0.5f;
|
||
|
|
|
||
|
|
GameObject floor = GameObject.CreatePrimitive(PrimitiveType.Cube);
|
||
|
|
floor.name = "Flat Stone Arena Floor";
|
||
|
|
floor.transform.position = new Vector3(0f, -0.08f, 0f);
|
||
|
|
floor.transform.localScale = new Vector3(arenaSize, 0.16f, arenaSize);
|
||
|
|
floor.GetComponent<Renderer>().sharedMaterial = materials["ArenaFloor"];
|
||
|
|
|
||
|
|
CreateWall("North Wall", new Vector3(0f, 1.15f, half), new Vector3(arenaSize + 1.2f, 2.3f, 0.8f), materials["ArenaWall"]);
|
||
|
|
CreateWall("South Wall", new Vector3(0f, 1.15f, -half), new Vector3(arenaSize + 1.2f, 2.3f, 0.8f), materials["ArenaWall"]);
|
||
|
|
CreateWall("East Wall", new Vector3(half, 1.15f, 0f), new Vector3(0.8f, 2.3f, arenaSize + 1.2f), materials["ArenaWall"]);
|
||
|
|
CreateWall("West Wall", new Vector3(-half, 1.15f, 0f), new Vector3(0.8f, 2.3f, arenaSize + 1.2f), materials["ArenaWall"]);
|
||
|
|
|
||
|
|
for (int i = -2; i <= 2; i++)
|
||
|
|
{
|
||
|
|
if (i == 0)
|
||
|
|
{
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
CreateFloorLine($"Floor Guide X {i}", new Vector3(i * 8f, 0.012f, 0f), new Vector3(0.05f, 0.02f, arenaSize - 5f), materials["ArenaLine"]);
|
||
|
|
CreateFloorLine($"Floor Guide Z {i}", new Vector3(0f, 0.014f, i * 8f), new Vector3(arenaSize - 5f, 0.02f, 0.05f), materials["ArenaLine"]);
|
||
|
|
}
|
||
|
|
|
||
|
|
Vector3[] blockPositions =
|
||
|
|
{
|
||
|
|
new Vector3(-16f, 0.55f, -13f), new Vector3(16f, 0.55f, -13f),
|
||
|
|
new Vector3(-16f, 0.55f, 13f), new Vector3(16f, 0.55f, 13f),
|
||
|
|
new Vector3(-7f, 0.45f, 18f), new Vector3(7f, 0.45f, 18f)
|
||
|
|
};
|
||
|
|
|
||
|
|
Vector3[] blockScales =
|
||
|
|
{
|
||
|
|
new Vector3(4.5f, 1.1f, 2f), new Vector3(4.5f, 1.1f, 2f),
|
||
|
|
new Vector3(2f, 1.1f, 4.5f), new Vector3(2f, 1.1f, 4.5f),
|
||
|
|
new Vector3(3.2f, 0.9f, 2f), new Vector3(3.2f, 0.9f, 2f)
|
||
|
|
};
|
||
|
|
|
||
|
|
for (int i = 0; i < blockPositions.Length; i++)
|
||
|
|
{
|
||
|
|
CreateWall($"Arena Cover {i + 1:00}", blockPositions[i], blockScales[i], materials["ArenaTrim"]);
|
||
|
|
}
|
||
|
|
|
||
|
|
Vector3[] columnPositions =
|
||
|
|
{
|
||
|
|
new Vector3(-22f, 1.7f, -22f), new Vector3(22f, 1.7f, -22f),
|
||
|
|
new Vector3(-22f, 1.7f, 22f), new Vector3(22f, 1.7f, 22f),
|
||
|
|
new Vector3(-22f, 1.7f, 0f), new Vector3(22f, 1.7f, 0f)
|
||
|
|
};
|
||
|
|
|
||
|
|
for (int i = 0; i < columnPositions.Length; i++)
|
||
|
|
{
|
||
|
|
GameObject pillar = GameObject.CreatePrimitive(PrimitiveType.Cylinder);
|
||
|
|
pillar.name = $"Stone Column {i + 1:00}";
|
||
|
|
pillar.transform.position = columnPositions[i];
|
||
|
|
pillar.transform.localScale = new Vector3(0.75f, 1.7f, 0.75f);
|
||
|
|
pillar.GetComponent<Renderer>().sharedMaterial = materials["ArenaWall"];
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private static void CreateWall(string name, Vector3 position, Vector3 scale, Material material)
|
||
|
|
{
|
||
|
|
GameObject wall = GameObject.CreatePrimitive(PrimitiveType.Cube);
|
||
|
|
wall.name = name;
|
||
|
|
wall.transform.position = position;
|
||
|
|
wall.transform.localScale = scale;
|
||
|
|
wall.GetComponent<Renderer>().sharedMaterial = material;
|
||
|
|
}
|
||
|
|
|
||
|
|
private static void CreateFloorLine(string name, Vector3 position, Vector3 scale, Material material)
|
||
|
|
{
|
||
|
|
GameObject line = GameObject.CreatePrimitive(PrimitiveType.Cube);
|
||
|
|
line.name = name;
|
||
|
|
line.transform.position = position;
|
||
|
|
line.transform.localScale = scale;
|
||
|
|
line.GetComponent<Renderer>().sharedMaterial = material;
|
||
|
|
Object.DestroyImmediate(line.GetComponent<Collider>());
|
||
|
|
}
|
||
|
|
|
||
|
|
private static GameObject BuildPlayer(Dictionary<string, Material> materials, params AbilityData[] abilities)
|
||
|
|
{
|
||
|
|
GameObject player = new GameObject("Player_Mage");
|
||
|
|
player.name = "Player_Mage";
|
||
|
|
player.transform.position = new Vector3(0f, 0f, -10f);
|
||
|
|
|
||
|
|
GameObject visual = GameObject.CreatePrimitive(PrimitiveType.Capsule);
|
||
|
|
visual.name = "Player_Visual";
|
||
|
|
visual.transform.SetParent(player.transform, false);
|
||
|
|
visual.transform.localPosition = Vector3.up;
|
||
|
|
visual.GetComponent<Renderer>().sharedMaterial = materials["Player"];
|
||
|
|
Object.DestroyImmediate(visual.GetComponent<CapsuleCollider>());
|
||
|
|
|
||
|
|
CharacterController controller = player.AddComponent<CharacterController>();
|
||
|
|
controller.height = 2f;
|
||
|
|
controller.radius = 0.42f;
|
||
|
|
controller.center = Vector3.up;
|
||
|
|
|
||
|
|
PlayerStats stats = player.AddComponent<PlayerStats>();
|
||
|
|
player.AddComponent<PlayerController>();
|
||
|
|
|
||
|
|
Transform castOrigin = new GameObject("CastOrigin").transform;
|
||
|
|
castOrigin.SetParent(player.transform, false);
|
||
|
|
castOrigin.localPosition = new Vector3(0f, 1.25f, 0.55f);
|
||
|
|
|
||
|
|
AbilityManager manager = player.AddComponent<AbilityManager>();
|
||
|
|
SetObject(manager, "playerStats", stats);
|
||
|
|
SetObject(manager, "castOrigin", castOrigin);
|
||
|
|
SetObjectArray(manager, "learnedAbilities", abilities);
|
||
|
|
return player;
|
||
|
|
}
|
||
|
|
|
||
|
|
private static void BuildCamera(Transform player)
|
||
|
|
{
|
||
|
|
GameObject cameraObject = new GameObject("Main Camera");
|
||
|
|
Camera camera = cameraObject.AddComponent<Camera>();
|
||
|
|
cameraObject.tag = "MainCamera";
|
||
|
|
camera.nearClipPlane = 0.05f;
|
||
|
|
camera.fieldOfView = 48f;
|
||
|
|
cameraObject.transform.position = player.position + new Vector3(0f, 11f, -9f);
|
||
|
|
cameraObject.transform.LookAt(player.position + Vector3.up * 1.3f);
|
||
|
|
ThirdPersonCamera follow = cameraObject.AddComponent<ThirdPersonCamera>();
|
||
|
|
follow.SetTarget(player);
|
||
|
|
SetFloat(follow, "mouseSensitivity", 1.8f);
|
||
|
|
SetFloat(follow, "smoothTime", 0.12f);
|
||
|
|
SetFloat(follow, "minPitch", 45f);
|
||
|
|
SetFloat(follow, "maxPitch", 60f);
|
||
|
|
SetFloat(follow, "initialPitch", 52f);
|
||
|
|
SetFloat(follow, "distance", 14f);
|
||
|
|
SetFloat(follow, "lookAhead", 3.5f);
|
||
|
|
SetFloat(follow, "targetHeight", 1.25f);
|
||
|
|
|
||
|
|
PlayerController controller = player.GetComponent<PlayerController>();
|
||
|
|
SetObject(controller, "cameraTransform", cameraObject.transform);
|
||
|
|
}
|
||
|
|
|
||
|
|
private static void BuildEnemies(GameObject enemyPrefab)
|
||
|
|
{
|
||
|
|
Vector3[] positions =
|
||
|
|
{
|
||
|
|
new Vector3(-15f, 1.35f, 8f), new Vector3(-7f, 1.35f, 14f), new Vector3(7f, 1.35f, 14f), new Vector3(15f, 1.35f, 8f),
|
||
|
|
new Vector3(-18f, 1.35f, -3f), new Vector3(18f, 1.35f, -3f), new Vector3(-9f, 1.35f, -18f), new Vector3(9f, 1.35f, -18f)
|
||
|
|
};
|
||
|
|
|
||
|
|
for (int i = 0; i < positions.Length; i++)
|
||
|
|
{
|
||
|
|
GameObject enemy = (GameObject)PrefabUtility.InstantiatePrefab(enemyPrefab);
|
||
|
|
enemy.name = $"Enemy_{i + 1:00}";
|
||
|
|
enemy.transform.position = positions[i];
|
||
|
|
enemy.transform.LookAt(new Vector3(0f, enemy.transform.position.y, -10f));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private static void BuildTrainingMannequins(Dictionary<string, Material> materials)
|
||
|
|
{
|
||
|
|
for (int i = 0; i < 4; i++)
|
||
|
|
{
|
||
|
|
float x = -9f + i * 6f;
|
||
|
|
GameObject body = GameObject.CreatePrimitive(PrimitiveType.Capsule);
|
||
|
|
body.name = $"Training Mannequin_{i + 1:00}";
|
||
|
|
body.transform.position = new Vector3(x, 1.1f, 21f);
|
||
|
|
body.transform.localScale = new Vector3(0.75f, 1.1f, 0.75f);
|
||
|
|
body.GetComponent<Renderer>().sharedMaterial = materials["Mannequin"];
|
||
|
|
|
||
|
|
GameObject cross = GameObject.CreatePrimitive(PrimitiveType.Cube);
|
||
|
|
cross.name = "Practice Armature";
|
||
|
|
cross.transform.SetParent(body.transform, false);
|
||
|
|
cross.transform.localPosition = new Vector3(0f, 0.35f, 0f);
|
||
|
|
cross.transform.localScale = new Vector3(1.8f, 0.12f, 0.12f);
|
||
|
|
cross.GetComponent<Renderer>().sharedMaterial = materials["ArenaTrim"];
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private static void BuildManaCrystals(GameObject crystalPrefab)
|
||
|
|
{
|
||
|
|
Vector3[] positions =
|
||
|
|
{
|
||
|
|
new Vector3(-21f, 0.1f, -12f),
|
||
|
|
new Vector3(21f, 0.1f, -12f),
|
||
|
|
new Vector3(-21f, 0.1f, 12f),
|
||
|
|
new Vector3(21f, 0.1f, 12f)
|
||
|
|
};
|
||
|
|
|
||
|
|
for (int i = 0; i < positions.Length; i++)
|
||
|
|
{
|
||
|
|
GameObject crystal = (GameObject)PrefabUtility.InstantiatePrefab(crystalPrefab);
|
||
|
|
crystal.name = $"Mana Crystal_{i + 1:00}";
|
||
|
|
crystal.transform.position = positions[i];
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private static void BuildFloatingDamageManager(FloatingDamage prefab)
|
||
|
|
{
|
||
|
|
GameObject manager = new GameObject("FloatingDamageManager");
|
||
|
|
FloatingDamageManager damageManager = manager.AddComponent<FloatingDamageManager>();
|
||
|
|
SetObject(damageManager, "floatingDamagePrefab", prefab);
|
||
|
|
}
|
||
|
|
|
||
|
|
private static void BuildUI(GameObject player, AbilitySlotUI slotPrefab, Font font, Dictionary<string, Material> materials)
|
||
|
|
{
|
||
|
|
GameObject canvasObject = new GameObject("Gameplay UI", typeof(RectTransform));
|
||
|
|
Canvas canvas = canvasObject.AddComponent<Canvas>();
|
||
|
|
canvas.renderMode = RenderMode.ScreenSpaceOverlay;
|
||
|
|
CanvasScaler scaler = canvasObject.AddComponent<CanvasScaler>();
|
||
|
|
scaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize;
|
||
|
|
scaler.referenceResolution = new Vector2(1280f, 720f);
|
||
|
|
scaler.matchWidthOrHeight = 0.5f;
|
||
|
|
canvasObject.AddComponent<GraphicRaycaster>();
|
||
|
|
|
||
|
|
GameObject eventSystem = new GameObject("EventSystem");
|
||
|
|
eventSystem.AddComponent<EventSystem>();
|
||
|
|
eventSystem.AddComponent<StandaloneInputModule>();
|
||
|
|
|
||
|
|
TooltipUI tooltip = BuildTooltip(canvasObject.transform, font);
|
||
|
|
BuildResourcePanel(canvasObject.transform, player.GetComponent<PlayerStats>(), font, false, new Vector2(24f, 72f), new Color(0.78f, 0.16f, 0.17f, 1f));
|
||
|
|
BuildResourcePanel(canvasObject.transform, player.GetComponent<PlayerStats>(), font, true, new Vector2(24f, 34f), new Color(0.12f, 0.55f, 0.95f, 1f));
|
||
|
|
BuildAbilityBar(canvasObject.transform, player.GetComponent<AbilityManager>(), slotPrefab, tooltip, font);
|
||
|
|
}
|
||
|
|
|
||
|
|
private static void BuildAbilityBar(Transform canvas, AbilityManager manager, AbilitySlotUI slotPrefab, TooltipUI tooltip, Font font)
|
||
|
|
{
|
||
|
|
GameObject panel = CreateUIObject("Ability Bar", canvas, new Vector2(0.5f, 0f), new Vector2(0.5f, 0f), new Vector2(0.5f, 0f), new Vector2(318f, 92f), new Vector2(0f, 18f));
|
||
|
|
Image back = panel.AddComponent<Image>();
|
||
|
|
back.color = new Color(0.025f, 0.03f, 0.035f, 0.72f);
|
||
|
|
|
||
|
|
GameObject root = CreateUIObject("Slots", panel.transform, Vector2.zero, Vector2.one, new Vector2(0.5f, 0.5f), new Vector2(-20f, -16f), Vector2.zero);
|
||
|
|
HorizontalLayoutGroup layout = root.AddComponent<HorizontalLayoutGroup>();
|
||
|
|
layout.spacing = 10f;
|
||
|
|
layout.childAlignment = TextAnchor.MiddleCenter;
|
||
|
|
layout.childControlWidth = false;
|
||
|
|
layout.childControlHeight = false;
|
||
|
|
layout.childForceExpandWidth = false;
|
||
|
|
layout.childForceExpandHeight = false;
|
||
|
|
|
||
|
|
AbilityBarUI bar = panel.AddComponent<AbilityBarUI>();
|
||
|
|
SetObject(bar, "abilityManager", manager);
|
||
|
|
SetObject(bar, "slotPrefab", slotPrefab);
|
||
|
|
SetObject(bar, "slotRoot", root.transform);
|
||
|
|
SetObject(bar, "tooltip", tooltip);
|
||
|
|
}
|
||
|
|
|
||
|
|
private static void BuildResourcePanel(Transform canvas, PlayerStats stats, Font font, bool mana, Vector2 anchoredPosition, Color fillColor)
|
||
|
|
{
|
||
|
|
GameObject panel = CreateUIObject(mana ? "Mana Bar" : "HP Bar", canvas, Vector2.zero, Vector2.zero, Vector2.zero, new Vector2(226f, 28f), anchoredPosition);
|
||
|
|
Image back = panel.AddComponent<Image>();
|
||
|
|
back.color = new Color(0.025f, 0.03f, 0.035f, 0.74f);
|
||
|
|
|
||
|
|
Text name = CreateText(mana ? "Mana Label" : "HP Label", panel.transform, font, mana ? "Mana" : "HP", 13, TextAnchor.MiddleLeft, new Color(0.9f, 0.92f, 0.94f, 1f));
|
||
|
|
Anchor(name.rectTransform, new Vector2(0f, 0f), new Vector2(0f, 1f), new Vector2(0f, 0.5f), new Vector2(50f, 0f), new Vector2(10f, 0f));
|
||
|
|
|
||
|
|
GameObject fillBackObject = CreateUIObject("Track", panel.transform, Vector2.zero, Vector2.one, new Vector2(0.5f, 0.5f), new Vector2(-62f, -10f), new Vector2(26f, 0f));
|
||
|
|
Image fillBack = fillBackObject.AddComponent<Image>();
|
||
|
|
fillBack.color = new Color(0f, 0f, 0f, 0.28f);
|
||
|
|
|
||
|
|
GameObject fillObject = CreateUIObject("Fill", panel.transform, Vector2.zero, Vector2.one, new Vector2(0f, 0.5f), new Vector2(-62f, -10f), new Vector2(26f, 0f));
|
||
|
|
Image fill = fillObject.AddComponent<Image>();
|
||
|
|
fill.color = fillColor;
|
||
|
|
fill.type = Image.Type.Filled;
|
||
|
|
fill.fillMethod = Image.FillMethod.Horizontal;
|
||
|
|
|
||
|
|
Text label = CreateText("Value", panel.transform, font, "100 / 100", 13, TextAnchor.MiddleRight, Color.white);
|
||
|
|
Anchor(label.rectTransform, new Vector2(1f, 0f), new Vector2(1f, 1f), new Vector2(1f, 0.5f), new Vector2(78f, 0f), new Vector2(-9f, 0f));
|
||
|
|
|
||
|
|
ResourceBarUI resource = panel.AddComponent<ResourceBarUI>();
|
||
|
|
SetObject(resource, "playerStats", stats);
|
||
|
|
SetBool(resource, "useMana", mana);
|
||
|
|
SetObject(resource, "fill", fill);
|
||
|
|
SetObject(resource, "valueLabel", label);
|
||
|
|
}
|
||
|
|
|
||
|
|
private static TooltipUI BuildTooltip(Transform canvas, Font font)
|
||
|
|
{
|
||
|
|
GameObject panel = CreateUIObject("Ability Tooltip", canvas, new Vector2(0.5f, 0f), new Vector2(0.5f, 0f), new Vector2(0.5f, 0f), new Vector2(280f, 172f), new Vector2(0f, 164f));
|
||
|
|
Image back = panel.AddComponent<Image>();
|
||
|
|
back.color = new Color(0.025f, 0.03f, 0.035f, 0.96f);
|
||
|
|
|
||
|
|
Text title = CreateText("Title", panel.transform, font, "Ability", 19, TextAnchor.MiddleLeft, Color.white);
|
||
|
|
title.horizontalOverflow = HorizontalWrapMode.Overflow;
|
||
|
|
title.verticalOverflow = VerticalWrapMode.Truncate;
|
||
|
|
Anchor(title.rectTransform, new Vector2(0f, 1f), new Vector2(1f, 1f), new Vector2(0.5f, 1f), new Vector2(-28f, 30f), new Vector2(0f, -20f));
|
||
|
|
|
||
|
|
Text description = CreateText("Description", panel.transform, font, "", 13, TextAnchor.UpperLeft, new Color(0.78f, 0.82f, 0.86f, 1f));
|
||
|
|
description.horizontalOverflow = HorizontalWrapMode.Wrap;
|
||
|
|
description.verticalOverflow = VerticalWrapMode.Truncate;
|
||
|
|
Anchor(description.rectTransform, new Vector2(0f, 0.42f), new Vector2(1f, 0.79f), new Vector2(0.5f, 0.5f), new Vector2(-28f, 0f), new Vector2(0f, -4f));
|
||
|
|
|
||
|
|
Text stats = CreateText("Stats", panel.transform, font, "", 14, TextAnchor.UpperLeft, new Color(0.48f, 0.88f, 1f, 1f));
|
||
|
|
stats.horizontalOverflow = HorizontalWrapMode.Wrap;
|
||
|
|
stats.verticalOverflow = VerticalWrapMode.Truncate;
|
||
|
|
Anchor(stats.rectTransform, new Vector2(0f, 0f), new Vector2(1f, 0.34f), new Vector2(0.5f, 0f), new Vector2(-28f, -12f), new Vector2(0f, 10f));
|
||
|
|
|
||
|
|
TooltipUI tooltip = panel.AddComponent<TooltipUI>();
|
||
|
|
SetObject(tooltip, "titleLabel", title);
|
||
|
|
SetObject(tooltip, "descriptionLabel", description);
|
||
|
|
SetObject(tooltip, "statsLabel", stats);
|
||
|
|
panel.SetActive(false);
|
||
|
|
return tooltip;
|
||
|
|
}
|
||
|
|
|
||
|
|
private static GameObject CreateUIObject(string name, Transform parent, Vector2 anchorMin, Vector2 anchorMax, Vector2 pivot, Vector2 size, Vector2 anchoredPosition)
|
||
|
|
{
|
||
|
|
GameObject obj = new GameObject(name, typeof(RectTransform));
|
||
|
|
RectTransform rect = obj.GetComponent<RectTransform>();
|
||
|
|
if (parent != null)
|
||
|
|
{
|
||
|
|
rect.SetParent(parent, false);
|
||
|
|
}
|
||
|
|
|
||
|
|
Anchor(rect, anchorMin, anchorMax, pivot, size, anchoredPosition);
|
||
|
|
return obj;
|
||
|
|
}
|
||
|
|
|
||
|
|
private static Text CreateText(string name, Transform parent, Font font, string text, int size, TextAnchor alignment, Color color)
|
||
|
|
{
|
||
|
|
GameObject obj = CreateUIObject(name, parent, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(120f, 30f), Vector2.zero);
|
||
|
|
Text label = obj.AddComponent<Text>();
|
||
|
|
label.font = font;
|
||
|
|
label.text = text;
|
||
|
|
label.fontSize = size;
|
||
|
|
label.alignment = alignment;
|
||
|
|
label.color = color;
|
||
|
|
label.horizontalOverflow = HorizontalWrapMode.Wrap;
|
||
|
|
label.verticalOverflow = VerticalWrapMode.Truncate;
|
||
|
|
label.raycastTarget = false;
|
||
|
|
Shadow shadow = obj.AddComponent<Shadow>();
|
||
|
|
shadow.effectColor = new Color(0f, 0f, 0f, 0.65f);
|
||
|
|
shadow.effectDistance = new Vector2(1f, -1f);
|
||
|
|
return label;
|
||
|
|
}
|
||
|
|
|
||
|
|
private static void Anchor(RectTransform rect, Vector2 anchorMin, Vector2 anchorMax, Vector2 pivot, Vector2 size, Vector2 anchoredPosition)
|
||
|
|
{
|
||
|
|
rect.anchorMin = anchorMin;
|
||
|
|
rect.anchorMax = anchorMax;
|
||
|
|
rect.pivot = pivot;
|
||
|
|
rect.sizeDelta = size;
|
||
|
|
rect.anchoredPosition = anchoredPosition;
|
||
|
|
}
|
||
|
|
|
||
|
|
private static void Stretch(RectTransform rect)
|
||
|
|
{
|
||
|
|
Anchor(rect, Vector2.zero, Vector2.one, new Vector2(0.5f, 0.5f), Vector2.zero, Vector2.zero);
|
||
|
|
}
|
||
|
|
|
||
|
|
private static GameObject SavePrefab(GameObject root, string path)
|
||
|
|
{
|
||
|
|
if (AssetDatabase.LoadAssetAtPath<GameObject>(path) != null)
|
||
|
|
{
|
||
|
|
AssetDatabase.DeleteAsset(path);
|
||
|
|
}
|
||
|
|
|
||
|
|
GameObject prefab = PrefabUtility.SaveAsPrefabAsset(root, path);
|
||
|
|
Object.DestroyImmediate(root);
|
||
|
|
return prefab;
|
||
|
|
}
|
||
|
|
|
||
|
|
private static void SetObject(Object target, string propertyName, Object value)
|
||
|
|
{
|
||
|
|
SerializedObject serializedObject = new SerializedObject(target);
|
||
|
|
SerializedProperty property = serializedObject.FindProperty(propertyName);
|
||
|
|
property.objectReferenceValue = value;
|
||
|
|
serializedObject.ApplyModifiedPropertiesWithoutUndo();
|
||
|
|
}
|
||
|
|
|
||
|
|
private static void SetObjectArray(Object target, string propertyName, Object[] values)
|
||
|
|
{
|
||
|
|
SerializedObject serializedObject = new SerializedObject(target);
|
||
|
|
SerializedProperty property = serializedObject.FindProperty(propertyName);
|
||
|
|
property.arraySize = values.Length;
|
||
|
|
for (int i = 0; i < values.Length; i++)
|
||
|
|
{
|
||
|
|
property.GetArrayElementAtIndex(i).objectReferenceValue = values[i];
|
||
|
|
}
|
||
|
|
|
||
|
|
serializedObject.ApplyModifiedPropertiesWithoutUndo();
|
||
|
|
}
|
||
|
|
|
||
|
|
private static void SetFloat(Object target, string propertyName, float value)
|
||
|
|
{
|
||
|
|
SerializedObject serializedObject = new SerializedObject(target);
|
||
|
|
SerializedProperty property = serializedObject.FindProperty(propertyName);
|
||
|
|
property.floatValue = value;
|
||
|
|
serializedObject.ApplyModifiedPropertiesWithoutUndo();
|
||
|
|
}
|
||
|
|
|
||
|
|
private static void SetVector3(Object target, string propertyName, Vector3 value)
|
||
|
|
{
|
||
|
|
SerializedObject serializedObject = new SerializedObject(target);
|
||
|
|
SerializedProperty property = serializedObject.FindProperty(propertyName);
|
||
|
|
property.vector3Value = value;
|
||
|
|
serializedObject.ApplyModifiedPropertiesWithoutUndo();
|
||
|
|
}
|
||
|
|
|
||
|
|
private static void SetBool(Object target, string propertyName, bool value)
|
||
|
|
{
|
||
|
|
SerializedObject serializedObject = new SerializedObject(target);
|
||
|
|
SerializedProperty property = serializedObject.FindProperty(propertyName);
|
||
|
|
property.boolValue = value;
|
||
|
|
serializedObject.ApplyModifiedPropertiesWithoutUndo();
|
||
|
|
}
|
||
|
|
}
|