This commit is contained in:
2026-07-09 21:33:33 +02:00
commit 84a2a365f3
2364 changed files with 950134 additions and 0 deletions
@@ -0,0 +1,178 @@
using System.Collections.Generic;
using System.Linq;
using InfinityPBR.ModularCharacterHelper;
using Sirenix.OdinInspector;
using Sirenix.Utilities;
using UnityEngine;
using VOID.Generic.Dict;
using VOID.Generic.Objects.Unit;
using VOID.Generic.Util;
using Random = UnityEngine.Random;
namespace VOID.ScriptableObjects
{
[CreateAssetMenu(menuName = "GAME DATA/Generator/Generator Jednostki")]
public class UnitGenerator : ScriptableObject
{
[Title("Unit References")]
[SerializeField] private UnitObject[] _unitPrefabs;
[SerializeField] private Material[] _skinMaterials;
[SerializeField] private Material[] _hairMaterials;
[Space(100)]
[Title("Model")]
[InfoBox("If prefab part can't be attached to unit prefab then it'll be skipped!")]
[SerializeField] private bool _generateHair;
[SerializeField, ShowIf(nameof(_generateHair)), Required] private ModularPart[] _hairPrefabs;
[Title("Colors")]
[InfoBox("If colors list is empty then randomize new one!")]
[SerializeField] private bool _generateSkinColor;
[SerializeField, ShowIf(nameof(_generateSkinColor))] private Color[] _skinColors;
[SerializeField] private bool _generateHairColor;
[SerializeField, ShowIf(nameof(_generateHairColor))] private Color[] _hairColors;
[Title("Main Attributes")]
[SerializeField] private bool _generateMainAttributes;
[SerializeField, ShowIf(nameof(_generateMainAttributes)), MinMaxSlider(1, 50, true)] private Vector2Int _strength = new(4, 7);
[SerializeField, ShowIf(nameof(_generateMainAttributes)), MinMaxSlider(1, 50, true)] private Vector2Int _dexterity = new(4, 7);
[SerializeField, ShowIf(nameof(_generateMainAttributes)), MinMaxSlider(1, 50, true)] private Vector2Int _intelligence = new(4, 7);
[SerializeField, ShowIf(nameof(_generateMainAttributes)), MinMaxSlider(1, 50, true)] private Vector2Int _constitution = new(4, 7);
[SerializeField, ShowIf(nameof(_generateMainAttributes)), MinMaxSlider(1, 50, true)] private Vector2Int _speed = new(4, 7);
[SerializeField, ShowIf(nameof(_generateMainAttributes)), MinMaxSlider(1, 50, true)] private Vector2Int _perception = new(4, 7);
private void OnValidate()
{
if (!_generateHair)
{
_hairPrefabs = null;
}
if (!_generateSkinColor)
{
_skinColors = null;
}
if (!_generateHairColor)
{
_hairColors = null;
}
if (!_generateMainAttributes)
{
_strength = new Vector2Int(4, 7);
_dexterity = new Vector2Int(4, 7);
_intelligence = new Vector2Int(4, 7);
_constitution = new Vector2Int(4, 7);
_speed = new Vector2Int(4, 7);
_perception = new Vector2Int(4, 7);
}
}
/// <summary>
/// Generate new <see cref="UnitObject"/>:<br/>
/// 1. Selects random <see cref="UnitObject"/> prefab<br/>
/// 2. Wait for full initialization of <see cref="UnitObject"/><br/>
/// 3. Updates <see cref="UnitObject"/> with random things defined via inspector
/// </summary>
/// <returns>Instantiated random <see cref="UnitObject"/></returns>
public UnitObject Generate(int? seed = null)
{
if (seed.HasValue) RandomUtil.InitState(seed.Value);
var unit = Instantiate(RandomUtil.RandomElement(_unitPrefabs));
Randomize(unit);
return unit;
}
private void Randomize(UnitObject unit)
{
RandomizeHair(unit);
RandomizeSkinColor(unit);
RandomizeHairColor(unit);
RandomizeMainAttributes(unit);
}
private void RandomizeHair(UnitObject unit)
{
if (!_generateHair) return;
var modularCharacter = unit.unitState.modularCharacter;
var validHairPrefabs = _hairPrefabs.Where(hair => hair.avatar == modularCharacter.avatar).ToList();
if (validHairPrefabs.IsNullOrEmpty()) return;
modularCharacter.AttachPart(Instantiate(RandomUtil.RandomElement(validHairPrefabs), unit.transform));
}
private void RandomizeSkinColor(UnitObject unit)
{
if (!_generateSkinColor) return;
if (_skinMaterials.IsNullOrEmpty()) return;
ApplyTintToMaterials(unit, _skinColors, _skinMaterials);
}
private void RandomizeHairColor(UnitObject unit)
{
if (!_generateHairColor) return;
if (_hairMaterials.IsNullOrEmpty()) return;
ApplyTintToMaterials(unit, _hairColors, _hairMaterials);
}
private void ApplyTintToMaterials(UnitObject unit, Color[] colors, Material[] forMaterials)
{
// Find renderers with this material to add tint color
var foundRenderers = unit.GetComponentsInChildren<Renderer>()
.Where(renderer => forMaterials.Any(material => renderer.sharedMaterials.Contains(material)))
.ToList();
if (foundRenderers.IsNullOrEmpty()) return;
// Get random defined color if present OR randomize new one
var color = colors.IsNullOrEmpty()
? Random.ColorHSV(0, 1, 0, 1, 0, 1, 0, 1)
: RandomUtil.RandomElement(colors);
// Normally renderers here will use shared materials, but we want to create colored "variants" thats why
// we need to instantiate material and add tint color if this is matching material. Other materials will
// instantiate too anyway even without our help so lets do all of them by ourselfs!
foreach (var foundRenderer in foundRenderers)
{
var materials = new List<Material>();
foreach (var sharedMaterial in foundRenderer.sharedMaterials)
{
if (forMaterials.Contains(sharedMaterial))
{
var material = Instantiate(sharedMaterial);
material.color = color;
materials.Add(material);
}
else
{
materials.Add(sharedMaterial);
}
}
foundRenderer.sharedMaterials = materials.ToArray();
}
}
private void RandomizeMainAttributes(UnitObject unit)
{
if (!_generateMainAttributes) return;
unit.unitData.baseMainAttributes.Set(MainAttributeType.Strength,
RandomUtil.RandomInteger(_strength.x, _strength.y));
unit.unitData.baseMainAttributes.Set(MainAttributeType.Dexterity,
RandomUtil.RandomInteger(_dexterity.x, _dexterity.y));
unit.unitData.baseMainAttributes.Set(MainAttributeType.Intelligence,
RandomUtil.RandomInteger(_intelligence.x, _intelligence.y));
unit.unitData.baseMainAttributes.Set(MainAttributeType.Constitution,
RandomUtil.RandomInteger(_constitution.x, _constitution.y));
unit.unitData.baseMainAttributes.Set(MainAttributeType.Speed,
RandomUtil.RandomInteger(_speed.x, _speed.y));
unit.unitData.baseMainAttributes.Set(MainAttributeType.Perception,
RandomUtil.RandomInteger(_perception.x, _perception.y));
}
}
}