Working on AI movement completed UI system etc

This commit is contained in:
Hazim Bin Ijaz 2025-08-13 19:17:14 +05:00
parent a09be91a00
commit d9badf5c6a
21 changed files with 573 additions and 14 deletions

View File

@ -160535,6 +160535,18 @@ RectTransform:
type: 3}
m_PrefabInstance: {fileID: 1019458777}
m_PrefabAsset: {fileID: 0}
--- !u!114 &1019458779 stripped
MonoBehaviour:
m_CorrespondingSourceObject: {fileID: 372725716160773496, guid: d208e0f3e2f10a440a15e9b095c4a0e8,
type: 3}
m_PrefabInstance: {fileID: 1019458777}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 30dcebf945ea1bc439c74273d4bf48f5, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!1001 &1021336978
PrefabInstance:
m_ObjectHideFlags: 0
@ -354747,12 +354759,16 @@ MonoBehaviour:
user: {fileID: 2042403783257441066}
slots:
- ability: {fileID: 11400000, guid: 238ff629516647b448b2d6517f15b364, type: 2}
abilityUiItem: {fileID: 3533359467842034143}
cdTimer: 0
- ability: {fileID: 11400000, guid: 2cdcec8b6c2310d46847af6f490ad3e8, type: 2}
abilityUiItem: {fileID: 1019458779}
cdTimer: 0
- ability: {fileID: 0}
abilityUiItem: {fileID: 0}
cdTimer: 0
- ability: {fileID: 0}
cdTimer: 0
- ability: {fileID: 0}
abilityUiItem: {fileID: 0}
cdTimer: 0
--- !u!1001 &2612565535725099600
PrefabInstance:
@ -355112,6 +355128,18 @@ RectTransform:
type: 3}
m_PrefabInstance: {fileID: 3533359467842034141}
m_PrefabAsset: {fileID: 0}
--- !u!114 &3533359467842034143 stripped
MonoBehaviour:
m_CorrespondingSourceObject: {fileID: 372725716160773496, guid: d208e0f3e2f10a440a15e9b095c4a0e8,
type: 3}
m_PrefabInstance: {fileID: 3533359467842034141}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 30dcebf945ea1bc439c74273d4bf48f5, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!1001 &3685549447243067346
PrefabInstance:
m_ObjectHideFlags: 0

View File

@ -12,7 +12,7 @@ GameObject:
- component: {fileID: 2242664937601471350}
- component: {fileID: 1137290063122843096}
m_Layer: 5
m_Name: Text (TMP)
m_Name: AbiliyNameText (TMP)
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
@ -32,10 +32,10 @@ RectTransform:
m_Children: []
m_Father: {fileID: 4918938079055515515}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 0}
m_AnchoredPosition: {x: 0, y: 17.2471}
m_SizeDelta: {x: 0, y: 34.4941}
m_AnchorMin: {x: 0, y: 1}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 0, y: -17.24704}
m_SizeDelta: {x: 0, y: 34.494095}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &2242664937601471350
CanvasRenderer:
@ -65,7 +65,7 @@ MonoBehaviour:
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_text: Ability 1
m_text: --
m_isRightToLeft: 0
m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
@ -166,9 +166,9 @@ RectTransform:
m_Children: []
m_Father: {fileID: 4918938079055515515}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 1}
m_AnchorMax: {x: 0.5, y: 1}
m_AnchoredPosition: {x: 0, y: -60.000023}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 120, y: 120}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &5111066452280026694
@ -209,6 +209,140 @@ MonoBehaviour:
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!1 &5864139777741960210
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 703745729791789310}
- component: {fileID: 7002079901696980481}
- component: {fileID: 5028474175908707617}
m_Layer: 5
m_Name: KeyText
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &703745729791789310
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5864139777741960210}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 4918938079055515515}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 0}
m_AnchoredPosition: {x: 0, y: 17.24704}
m_SizeDelta: {x: 0, y: 34.494095}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &7002079901696980481
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5864139777741960210}
m_CullTransparentMesh: 1
--- !u!114 &5028474175908707617
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5864139777741960210}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_text: --
m_isRightToLeft: 0
m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
m_fontSharedMaterials: []
m_fontMaterial: {fileID: 0}
m_fontMaterials: []
m_fontColor32:
serializedVersion: 2
rgba: 4294967295
m_fontColor: {r: 1, g: 1, b: 1, a: 1}
m_enableVertexGradient: 0
m_colorMode: 3
m_fontColorGradient:
topLeft: {r: 1, g: 1, b: 1, a: 1}
topRight: {r: 1, g: 1, b: 1, a: 1}
bottomLeft: {r: 1, g: 1, b: 1, a: 1}
bottomRight: {r: 1, g: 1, b: 1, a: 1}
m_fontColorGradientPreset: {fileID: 0}
m_spriteAsset: {fileID: 0}
m_tintAllSprites: 0
m_StyleSheet: {fileID: 0}
m_TextStyleHashCode: -1183493901
m_overrideHtmlColors: 0
m_faceColor:
serializedVersion: 2
rgba: 4294967295
m_fontSize: 30.85
m_fontSizeBase: 36
m_fontWeight: 400
m_enableAutoSizing: 1
m_fontSizeMin: 18
m_fontSizeMax: 43
m_fontStyle: 0
m_HorizontalAlignment: 2
m_VerticalAlignment: 512
m_textAlignment: 65535
m_characterSpacing: 0
m_wordSpacing: 0
m_lineSpacing: 0
m_lineSpacingMax: 0
m_paragraphSpacing: 0
m_charWidthMaxAdj: 0
m_enableWordWrapping: 1
m_wordWrappingRatios: 0.4
m_overflowMode: 0
m_linkedTextComponent: {fileID: 0}
parentLinkedComponent: {fileID: 0}
m_enableKerning: 1
m_enableExtraPadding: 0
checkPaddingRequired: 0
m_isRichText: 1
m_parseCtrlCharacters: 1
m_isOrthographic: 1
m_isCullingEnabled: 0
m_horizontalMapping: 0
m_verticalMapping: 0
m_uvLineOffset: 0
m_geometrySortingOrder: 0
m_IsTextObjectScaleStatic: 0
m_VertexBufferAutoSizeReduction: 0
m_useMaxVisibleDescender: 1
m_pageToDisplay: 1
m_margin: {x: 0, y: 0, z: 0, w: 0}
m_isUsingLegacyAnimationComponent: 0
m_isVolumetricText: 0
m_hasFontAssetChanged: 0
m_baseMaterial: {fileID: 0}
m_maskOffset: {x: 0, y: 0, z: 0, w: 0}
--- !u!1 &8450869184831564982
GameObject:
m_ObjectHideFlags: 0
@ -218,6 +352,7 @@ GameObject:
serializedVersion: 6
m_Component:
- component: {fileID: 4918938079055515515}
- component: {fileID: 372725716160773496}
m_Layer: 5
m_Name: AbilityUIItem
m_TagString: Untagged
@ -239,10 +374,26 @@ RectTransform:
m_Children:
- {fileID: 6280358973369407615}
- {fileID: 1233609033755628515}
- {fileID: 703745729791789310}
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchoredPosition: {x: -32.887497, y: 11.3029}
m_SizeDelta: {x: 120, y: 157.6877}
m_AnchoredPosition: {x: -32.887497, y: -3.9686}
m_SizeDelta: {x: 120, y: 188.2307}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &372725716160773496
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8450869184831564982}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 30dcebf945ea1bc439c74273d4bf48f5, type: 3}
m_Name:
m_EditorClassIdentifier:
abilityIcon: {fileID: 4802381344739625320}
abilityName: {fileID: 1137290063122843096}
abilityKeyText: {fileID: 5028474175908707617}

View File

@ -0,0 +1,21 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: a39eb7f0fc0fd394abd3f393fb93ef34, type: 3}
m_Name: Channel Heal Ability
m_EditorClassIdentifier:
displayName: Channel Heal
icon: {fileID: 10913, guid: 0000000000000000f000000000000000, type: 0}
manaCost: 10
cooldown: 2
description:
channelTime: 5
healAmount: 50

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 2cdcec8b6c2310d46847af6f490ad3e8
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View File

@ -10,7 +10,7 @@ MonoBehaviour:
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 9285d1b57504d78469204d8011a14dff, type: 3}
m_Name: New Fireball Ability
m_Name: Fireball Ability
m_EditorClassIdentifier:
displayName: Fireball
icon: {fileID: 10913, guid: 0000000000000000f000000000000000, type: 0}

View File

@ -0,0 +1,50 @@
using System.Collections;
using UnityEngine;
[CreateAssetMenu(menuName = "Abilities/Channel Heal")]
public class ChannelHealAbility : Ability
{
public float channelTime = 5f; // seconds to wait
public float healAmount = 50f; // how much to heal
public override void Activate(AbilityUser user)
{
if (!user) return;
user.StartCoroutine(ChannelRoutine(user));
}
private IEnumerator ChannelRoutine(AbilityUser user)
{
float elapsed = 0f;
while (elapsed < channelTime)
{
// Cancel if player moves
if (IsPlayerMoving())
{
Debug.Log("Heal cancelled: player moved.");
yield break;
}
elapsed += Time.deltaTime;
yield return null;
}
// Heal and spend mana on completion
if (user.mana && !user.mana.Spend(manaCost))
{
Debug.Log("Not enough mana to complete heal.");
yield break;
}
if (user.health) user.health.Heal(healAmount);
Debug.Log($"Healed {healAmount} HP after channel.");
}
private bool IsPlayerMoving()
{
float h = Input.GetAxisRaw("Horizontal");
float v = Input.GetAxisRaw("Vertical");
return (Mathf.Abs(h) > 0.01f || Mathf.Abs(v) > 0.01f);
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a39eb7f0fc0fd394abd3f393fb93ef34
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,39 @@
using UnityEngine;
[CreateAssetMenu(menuName = "Abilities/Freeze Shard")]
public class FreezeShardAbility : Ability
{
public GameObject projectilePrefab;
public float speed = 20f;
public float damage = 0f; // optional direct damage
public float freezeDuration = 3f;
public float lifeTime = 4f;
public float spawnOffset = 0.5f;
public override void Activate(AbilityUser user)
{
if (!user || !projectilePrefab) return;
var pos = user.CastPos() + user.Forward() * spawnOffset;
var rot = Quaternion.LookRotation(user.Forward());
var go = Instantiate(projectilePrefab, pos, rot);
var rb = go.GetComponent<Rigidbody>();
if (rb) rb.velocity = user.Forward() * speed;
var shard = go.GetComponent<FreezeShardProjectile>();
if (!shard) shard = go.AddComponent<FreezeShardProjectile>();
shard.damage = damage;
shard.freezeDuration = freezeDuration;
shard.ownerRoot = user.transform;
var projCol = go.GetComponent<Collider>();
if (projCol)
{
foreach (var oc in user.GetComponentsInChildren<Collider>())
Physics.IgnoreCollision(projCol, oc, true);
}
Destroy(go, lifeTime);
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 49bbd40b4b6c27046ad28ab6eb3de43e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,3 +1,4 @@
using System;
using UnityEngine;
public class AbilityInput : MonoBehaviour
@ -6,6 +7,17 @@ public class AbilityInput : MonoBehaviour
public AbilityUser user;
public AbilitySlot[] slots = new AbilitySlot[4];
private void Start()
{
foreach (var slot in slots)
{
if (slot.abilityUiItem)
{
slot.abilityUiItem.Init(slot.ability);
}
}
}
void Update()
{
foreach (var s in slots) s?.Tick(Time.deltaTime);

View File

@ -4,6 +4,7 @@ using UnityEngine;
public class AbilitySlot
{
public Ability ability;
public AbilityUIItem abilityUiItem;
[HideInInspector] public float cdTimer; // counts down at runtime
public bool IsOnCooldown => cdTimer > 0f;

View File

@ -0,0 +1,121 @@
using UnityEngine;
using UnityEngine.AI;
using System.Collections;
[RequireComponent(typeof(NavMeshAgent))]
public class FreezableNavAgent : MonoBehaviour, IFreezable
{
[Header("Optional")]
[SerializeField] Animator animator; // optional: pause/resume anim
[SerializeField] string speedParam = "Speed"; // optional: set 0 while frozen
// Saved agent settings
float _origSpeed, _origAccel, _origAngSpeed;
bool _frozen;
Coroutine _freezeCo;
NavMeshAgent _agent;
void Awake()
{
_agent = GetComponent<NavMeshAgent>();
if (!animator) animator = GetComponentInChildren<Animator>();
CacheOriginals();
}
void OnEnable() { CacheOriginals(); }
void CacheOriginals()
{
if (_agent == null) return;
_origSpeed = _agent.speed;
_origAccel = _agent.acceleration;
_origAngSpeed = _agent.angularSpeed;
}
public void Freeze(float duration)
{
// If already frozen, refresh duration
if (_freezeCo != null) StopCoroutine(_freezeCo);
_freezeCo = StartCoroutine(FreezeRoutine(duration));
}
IEnumerator FreezeRoutine(float duration)
{
// Enter freeze
if (!_frozen) EnterFreeze();
// Wait for duration
float t = duration;
while (t > 0f)
{
t -= Time.deltaTime;
yield return null;
}
// Exit
ExitFreeze();
_freezeCo = null;
}
void EnterFreeze()
{
_frozen = true;
// Stop movement immediately
if (_agent)
{
_agent.isStopped = true; // halts pathfinding updates
_agent.ResetPath(); // clear current path
_agent.velocity = Vector3.zero;
// Optional: zero out movement-related params to avoid jitter
_agent.speed = 0f;
_agent.acceleration = 0f;
_agent.angularSpeed = 0f;
}
// Pause animations
if (animator)
{
animator.speed = 0f;
if (!string.IsNullOrEmpty(speedParam) && animator.HasParameterOfType(speedParam, AnimatorControllerParameterType.Float))
animator.SetFloat(speedParam, 0f);
}
}
void ExitFreeze()
{
_frozen = false;
if (_agent)
{
// Restore movement settings
_agent.speed = _origSpeed;
_agent.acceleration = _origAccel;
_agent.angularSpeed = _origAngSpeed;
_agent.isStopped = false;
}
if (animator)
{
animator.speed = 1f;
// (Your AI animation controller will resume updating speedParam from its movement script)
}
}
// Handy debug
[ContextMenu("Debug/Freeze 2s")]
void DebugFreeze2() => Freeze(2f);
}
// Small helper so we can safely check an Animator param
static class AnimatorExt
{
public static bool HasParameterOfType(this Animator self, string name, AnimatorControllerParameterType type)
{
foreach (var p in self.parameters)
if (p.type == type && p.name == name) return true;
return false;
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0fa5d25552156d040b84773c3488e856
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,31 @@
using UnityEngine;
using System.Collections;
public class FreezeShardProjectile : MonoBehaviour
{
public float damage;
public float freezeDuration;
public Transform ownerRoot;
public float armTime = 0.05f;
float spawnTime;
void Awake() => spawnTime = Time.time;
void OnTriggerEnter(Collider other)
{
if (Time.time - spawnTime < armTime) return;
if (ownerRoot && other.transform.root == ownerRoot) return;
if (other.TryGetComponent<IDamageable>(out var dmg))
{
if (damage > 0) dmg.ApplyDamage(damage);
}
if (other.TryGetComponent<IFreezable>(out var freezable))
{
freezable.Freeze(freezeDuration);
}
Destroy(gameObject);
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3f8a87ffd94add94f81964c4de32beb2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,4 @@
public interface IFreezable
{
void Freeze(float duration);
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2bc48da20a9b35745816045624cbdfd3
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

8
Assets/Scripts/UI.meta Normal file
View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: abdf3871aa2f985469f4153ebdff67f9
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,19 @@
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
public class AbilityUIItem : MonoBehaviour
{
[SerializeField] private Image abilityIcon;
[SerializeField] private TMP_Text abilityName;
[SerializeField] private TMP_Text abilityKeyText;
public void Init(Ability ability)
{
this.abilityIcon.sprite = ability.icon;
this.abilityName.text = ability.displayName;
this.abilityKeyText = abilityKeyText;
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 30dcebf945ea1bc439c74273d4bf48f5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: