(client) feat:实现热重载,实现多维度,实现武器,实现掉落物,实现状态UI,实现攻击AI #44

Merged
TheRedApricot merged 10 commits from zzdxxz/Gen_Hack-and-Slash-Roguelite-zzdxxz:temp820 into main 2025-08-27 19:56:50 +08:00
49 changed files with 11070 additions and 1571 deletions
Showing only changes of commit da93368f02 - Show all commits

File diff suppressed because it is too large Load Diff

View File

@ -6,9 +6,6 @@ namespace CameraControl
{
public class CameraControl : Utils.MonoSingleton<CameraControl>, ITick, ITickUI
{
// 当前被聚焦的目标实体
public Entity.Entity focusedEntity = null;
// Camera movement variables
private Vector3 _dragOrigin;
private bool _isDragging = false;
@ -50,12 +47,12 @@ namespace CameraControl
}
public void Tick()
{
if (focusedEntity)
if (Program.Instance.focusedEntity)
{
// Follow the focused entity's position
var targetPosition = new Vector3(
focusedEntity.Position.x,
focusedEntity.Position.y,
Program.Instance.focusedEntity.Position.x,
Program.Instance.focusedEntity.Position.y,
_camera.transform.position.z);
_camera.transform.position = Vector3.Lerp(
@ -86,7 +83,8 @@ namespace CameraControl
{
_dragOrigin = _camera.ScreenToWorldPoint(Input.mousePosition);
_isDragging = true;
focusedEntity = null; // Clear focus when manually moving camera
Program.Instance.focusedEntity.PlayerControlled = false;
Program.Instance.focusedEntity = null; // Clear focus when manually moving camera
}
// During drag

View File

@ -271,17 +271,17 @@ namespace Configs
public static Dictionary<string, T> LoadResources<T>(string path) where T : UnityEngine.Object
{
// 创建一个字典来存储资源名称和加载好的资源
Dictionary<string, T> resourceDict = new Dictionary<string, T>();
var resourceDict = new Dictionary<string, T>();
// 加载指定路径下的所有资源
T[] resources = Resources.LoadAll<T>(path);
var resources = Resources.LoadAll<T>(path);
foreach (T resource in resources)
foreach (var resource in resources)
{
if (resource != null)
{
// 获取资源名称并存入字典
string resourceName = resource.name;
var resourceName = resource.name;
resourceDict[resourceName] = resource;
}
}
@ -314,7 +314,7 @@ namespace Configs
try
{
// 使用 using 自动管理 FileStream 的生命周期
using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
using (var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
{
fs.Seek(0, SeekOrigin.Begin); // 将游标移动到文件开头(可选)
bytes = new byte[fs.Length]; // 创建一个字节数组来存储文件内容
@ -328,10 +328,14 @@ namespace Configs
}
// 创建一个默认大小的 Texture2D 对象
Texture2D texture = new Texture2D(2, 2); // 初始大小为 2x2LoadImage 会自动调整大小
var texture = new Texture2D(2, 2, TextureFormat.RGBA32, false); // 初始大小为 2x2LoadImage 会自动调整大小
if (texture.LoadImage(bytes)) // 加载图片数据
{
// 设置过滤模式为 Point (无插值)
texture.filterMode = FilterMode.Point;
texture.wrapMode = TextureWrapMode.Clamp; // 防止边缘出现意外拉伸
return texture; // 返回加载成功的 Texture2D 对象
}
else

View File

@ -227,7 +227,7 @@ namespace Data
public class DrawNodeDef : Define
{
public List<string> animationTextures = new();
public List<string> textures = new();
public List<DrawNodeDef> nodes = new();
public string nodeName;
public Vector2 position = new(0, 0);

View File

@ -54,10 +54,8 @@ namespace Entity
return;
// 计算当前向上方向与目标方向之间的角度
float angle = Mathf.Atan2(targetDirection.y, targetDirection.x) * Mathf.Rad2Deg;
// 调整角度因为默认贴图向上是0度而Atan2计算的是相对于x轴的角度
angle -= 90f;
var angle = Mathf.Atan2(targetDirection.y, targetDirection.x) * Mathf.Rad2Deg;
// 应用旋转
transform.rotation = Quaternion.Euler(0f, 0f, angle);

View File

@ -84,12 +84,20 @@ namespace Entity
{
IsChase = true;
currentJob = null;
if(Program.Instance.focusedEntity)
Program.Instance.focusedEntity.PlayerControlled = false;
Program.Instance.focusedEntity = this;
}
else if (PlayerControlled)
{
Program.Instance.focusedEntity = null;
}
_isPlayerControlled = value;
}
get => _isPlayerControlled;
get => Program.Instance.focusedEntity == this;
}
public bool IsWalking => _walkingTimer > 0;
/// <summary>
/// 获取实体当前位置。
/// </summary>
@ -99,18 +107,16 @@ namespace Entity
/// 表示实体是否已经死亡(生命值小于等于零)。
/// </summary>
public bool IsDead => attributes.health <= 0;
public bool IsShowingHealthBarUI=>hitBarUIShowTimer > 0;
public bool IsAttacking => attackCoroutine != null;
public bool IsShowingHealthBarUI=>_hitBarUIShowTimer > 0;
public bool IsAttacking => _attackCoroutine != null;
private bool _isPlayerControlled = false;
private bool _warning = false;
/// <summary>
/// 存储不同朝向下的动画节点集合。
/// </summary>
public Dictionary<EntityState, Dictionary<Orientation, List<ITick>>> bodyAnimationNode = new();
private List<ITick> currentAnimatorCache=new ();
private List<ITick> _currentAnimatorCache=new ();
/// <summary>
/// 存储不同朝向下的身体节点对象。
/// </summary>
@ -119,30 +125,31 @@ namespace Entity
/// <summary>
/// 当前实体的朝向。
/// </summary>
private Orientation currentOrientation = Orientation.Down;
private Orientation _currentOrientation = Orientation.Down;
/// <summary>
/// 当前实体的状态
/// </summary>
private EntityState currentState = EntityState.Idle;
private EntityState _currentState = EntityState.Idle;
/// <summary>
/// 攻击动画的持续时间(秒)。
/// </summary>
private const float attackAnimationDuration = 0.1f;
private const float AttackAnimationDuration = 0.1f;
/// <summary>
/// 抖动的偏移量。
/// </summary>
private const float shakeOffset = 0.5f;
private const float ShakeOffset = 0.5f;
// 协程引用
private Coroutine attackCoroutine;
private Coroutine _attackCoroutine;
protected EntityDef entityDef;
public float hitBarUIShowTime = 5;
private float hitBarUIShowTimer = 0;
[SerializeField] private float _hitBarUIShowTime = 5;
private float _hitBarUIShowTimer = 0;
private int _walkingTimer = 1;
/// <summary>
@ -258,7 +265,7 @@ namespace Entity
GameObject nodeObject = null;
// 根据纹理数量创建不同类型的节点
switch (drawNode.animationTextures?.Count ?? 0)
switch (drawNode.textures?.Count ?? 0)
{
case 0:
// 无纹理节点
@ -277,12 +284,12 @@ namespace Entity
nodeObject = Instantiate(imagePrefab.gameObject, parent.transform);
var texture =
Managers.PackagesImageManager.Instance?.GetSprite(drawNode.packID,
drawNode.animationTextures[0]);
drawNode.textures[0]);
if (!texture)
{
Debug.LogWarning(
$"InitBodyPart: 无法获取纹理 (节点名: {drawNode.nodeName}, 纹理ID: {drawNode.animationTextures[0]})");
$"InitBodyPart: 无法获取纹理 (节点名: {drawNode.nodeName}, 纹理ID: {drawNode.textures[0]})");
}
var imagePrefabCom = nodeObject.GetComponent<ImagePrefab>();
@ -316,7 +323,7 @@ namespace Entity
animator.SetFPS(drawNode.FPS);
var animatedSprites = new List<Sprite>();
foreach (var textureId in drawNode.animationTextures)
foreach (var textureId in drawNode.textures)
{
try
{
@ -386,7 +393,15 @@ namespace Entity
/// </summary>
public void Tick()
{
if (_isPlayerControlled)
if (_walkingTimer > 0)
{
_walkingTimer -= 1;
if (_walkingTimer <= 0)
{
SetBodyTexture(EntityState.Idle, _currentOrientation);
}
}
if (PlayerControlled)
{
UpdatePlayerControls();
}
@ -395,9 +410,9 @@ namespace Entity
AutoBehave();
}
if (currentAnimatorCache!=null)
if (_currentAnimatorCache!=null)
{
foreach (var animator in currentAnimatorCache)
foreach (var animator in _currentAnimatorCache)
{
animator.Tick();
}
@ -406,8 +421,8 @@ namespace Entity
if (IsShowingHealthBarUI)
{
hitBarUIShowTimer -= Time.deltaTime;
if (hitBarUIShowTimer <= 0)
_hitBarUIShowTimer -= Time.deltaTime;
if (_hitBarUIShowTimer <= 0)
{
HideHealthBar();
}
@ -420,14 +435,14 @@ namespace Entity
public virtual void TryAttack()
{
if(!IsAttacking)
attackCoroutine = StartCoroutine(AttackFlow());
_attackCoroutine = StartCoroutine(AttackFlow());
}
public virtual void SetBodyTexture(EntityState state, Orientation orientation)
{
if (bodyNodes.TryGetValue(currentState, out var stateNode))
if (bodyNodes.TryGetValue(_currentState, out var stateNode))
{
if (stateNode.TryGetValue(currentOrientation, out var node))
if (stateNode.TryGetValue(_currentOrientation, out var node))
{
node.SetActive(false);
}
@ -441,14 +456,14 @@ namespace Entity
}
}
currentState = state;
currentOrientation = orientation;
_currentState = state;
_currentOrientation = orientation;
if (bodyAnimationNode.TryGetValue(currentState, out var animationNode))
if (bodyAnimationNode.TryGetValue(_currentState, out var animationNode))
{
if (animationNode.TryGetValue(currentOrientation, out var value))
if (animationNode.TryGetValue(_currentOrientation, out var value))
{
currentAnimatorCache=value;
_currentAnimatorCache=value;
}
}
}
@ -461,6 +476,8 @@ namespace Entity
if (IsAttacking)
return;
transform.position += direction * (attributes.moveSpeed * Time.deltaTime * (IsChase ? 1 : 0.5f));
SetBodyTexture(EntityState.Walking,_currentOrientation);
_walkingTimer = 2;
}
/// <summary>
@ -483,7 +500,7 @@ namespace Entity
return;
healthBarPrefab.gameObject.SetActive(true);
healthBarPrefab.Progress = (float)attributes.health / entityDef.attributes.health;
hitBarUIShowTimer=hitBarUIShowTime;
_hitBarUIShowTimer=_hitBarUIShowTime;
}
public void HideHealthBar()
@ -521,7 +538,7 @@ namespace Entity
ori = direction.x > 0 ? Orientation.Right : Orientation.Left;
}
SetBodyTexture(currentState, ori);
SetBodyTexture(_currentState, ori);
}
/// <summary>
@ -608,7 +625,7 @@ namespace Entity
// 调用检测并攻击敌人的方法
DetectAndAttackEnemies();
// 攻击流程结束,清理协程引用
attackCoroutine = null;
_attackCoroutine = null;
}
@ -623,14 +640,14 @@ namespace Entity
StartCoroutine(ShakeInDirectionCoroutine());
// 返回检测敌人的起始时间
return attackAnimationDuration;
return AttackAnimationDuration;
}
private IEnumerator ShakeInDirectionCoroutine()
{
var originalPosition = transform.position; // 记录原始位置
transform.position += direction * shakeOffset;
yield return new WaitForSeconds(attackAnimationDuration);
transform.position += direction * ShakeOffset;
yield return new WaitForSeconds(AttackAnimationDuration);
transform.position = originalPosition;
}

View File

@ -110,14 +110,6 @@ namespace Entity
result.Add(("结束操控", EndControl));
else
result.Add(("手动操控", StartControl));
if (CameraControl.CameraControl.Instance.focusedEntity == entity)
{
result.Add(("取消跟随", ()=>CameraControl.CameraControl.Instance.focusedEntity=null));
}
else
{
result.Add(("视角跟随", ()=>CameraControl.CameraControl.Instance.focusedEntity=entity));
}
result.Add(("杀死", () => entity.Kill()));
result.Add(("变成笨蛋", BecomeDefault));
return result;
@ -132,13 +124,11 @@ namespace Entity
private void StartControl()
{
entity.PlayerControlled = true;
CameraControl.CameraControl.Instance.focusedEntity=entity;
}
private void EndControl()
{
entity.PlayerControlled = false;
CameraControl.CameraControl.Instance.focusedEntity=null;
}
}
}

View File

@ -296,15 +296,19 @@ namespace Managers
var textureWidth = texture.width;
var textureHeight = texture.height;
// 如果不分割rows和cols都为1直接创建单个Sprite
// 首先创建一个未分割的精灵,使用原始名称
if (!sprites.ContainsKey(packId))
sprites[packId] = new Dictionary<string, Sprite>();
// 创建未分割的精灵
var fullSpriteRect = new Rect(0, 0, textureWidth, textureHeight);
var fullSprite = Sprite.Create(texture, fullSpriteRect, new Vector2(0.5f, 0.5f), pixelsPerUnit);
fullSprite.name = baseName; // 使用原始名称
sprites[packId][baseName] = fullSprite;
// 如果不分割rows和cols都为1直接返回
if (rows == 1 && cols == 1)
{
if (!sprites.ContainsKey(packId))
sprites[packId] = new Dictionary<string, Sprite>();
var spriteRect = new Rect(0, 0, textureWidth, textureHeight);
var sprite = Sprite.Create(texture, spriteRect, new Vector2(0.5f, 0.5f), pixelsPerUnit);
sprites[packId][baseName] = sprite;
return;
}
@ -316,25 +320,25 @@ namespace Managers
Debug.LogError("Texture dimensions are not divisible by the specified rows and columns.");
return;
}
if (!sprites.ContainsKey(packId))
sprites[packId] = new Dictionary<string, Sprite>();
// 分割纹理并创建多个精灵
for (var row = 0; row < rows; row++)
{
for (var col = 0; col < cols; col++)
{
Rect spriteRect = new(col * tileWidth, row * tileHeight, tileWidth, tileHeight);
var sprite = Sprite.Create(texture, spriteRect, new Vector2(0.5f, 0.5f), pixelsPerUnit);
var index = (rows - row - 1) * cols + col;
var index = (rows - row - 1) * cols + col; // 计算索引
var spriteName = $"{baseName}_{index}";
sprite.name = spriteName;
// 添加到字典中
sprites[packId][spriteName] = sprite;
}
}
}
public void Reload()
{
packagesImages.Clear();

View File

@ -4,7 +4,7 @@ using UnityEngine.Tilemaps;
namespace Map
{
public class MapGenerator:Utils.MonoSingleton<MapGenerator>
public class MapGenerator:MonoBehaviour
{
public DoubleMap baseLevel;
public Tilemap buildLevel;
@ -24,10 +24,6 @@ namespace Map
{
return 0;
}
protected override void OnStart()
{
}
}
}

View File

@ -3,5 +3,7 @@ using UnityEngine;
public class Program : Utils.Singleton<Program>
{
public Entity.Entity focusedEntity = null;
public bool needLoad = true;
}

View File

@ -1,183 +0,0 @@
using System.Collections.Generic;
using UnityEngine;
namespace Utils
{
public static class Pathfinder
{
public static List<Vector2> FindPath(Entity.Entity entity, Vector2 target, float maxDistance)
{
Vector2 start = entity.Position;
// 计算起点和终点所在的瓦片坐标
var startTile = GetTileCoord(start);
var endTile = GetTileCoord(target);
// 如果超出最大距离,直接返回直线路径或空路径
if (Vector2.Distance(start, target) > maxDistance)
{
return new List<Vector2> { start, target };
}
// A*算法数据结构
var cameFrom = new Dictionary<Vector2Int, Vector2Int>();
var gScore = new Dictionary<Vector2Int, float>();
var fScore = new Dictionary<Vector2Int, float>();
var openSet = new List<Vector2Int>();
// 初始化
gScore[startTile] = 0;
fScore[startTile] = Heuristic(startTile, endTile);
openSet.Add(startTile);
var closestNode = startTile;
var closestDist = Vector2.Distance(start, target);
while (openSet.Count > 0)
{
// 获取fScore最小的节点
var current = openSet[0];
foreach (var node in openSet)
{
if (fScore.GetValueOrDefault(node, float.MaxValue) <
fScore.GetValueOrDefault(current, float.MaxValue))
{
current = node;
}
}
// 检查是否到达目标
if (current == endTile)
{
return ReconstructPath(cameFrom, current, start, target);
}
openSet.Remove(current);
// 检查最大距离限制
var currentDist = Vector2.Distance(
new Vector2(current.x, current.y),
target);
if (currentDist < closestDist)
{
closestDist = currentDist;
closestNode = current;
}
if (gScore[current] > maxDistance)
{
return ReconstructPath(cameFrom, closestNode, start, target);
}
// 遍历邻居8方向
for (var dx = -1; dx <= 1; dx++)
{
for (var dy = -1; dy <= 1; dy++)
{
if (dx == 0 && dy == 0) continue;
var neighbor = new Vector2Int(current.x + dx, current.y + dy);
// 跳过不可通行区域
if (!Map.MapGenerator.Instance.CanPassThrough(neighbor.x, neighbor.y))
{
continue;
}
// 计算移动成本
var moveCost = GetMovementCost(current, neighbor);
var tentativeGScore = gScore[current] + moveCost;
// 跳过超出最大距离的路径
if (tentativeGScore > maxDistance)
{
continue;
}
// 发现新节点或找到更好路径
if (tentativeGScore < gScore.GetValueOrDefault(neighbor, float.MaxValue))
{
cameFrom[neighbor] = current;
gScore[neighbor] = tentativeGScore;
fScore[neighbor] = tentativeGScore + Heuristic(neighbor, endTile);
if (!openSet.Contains(neighbor))
{
openSet.Add(neighbor);
}
}
}
}
}
// 无法找到完整路径时返回局部最优解
return ReconstructPath(cameFrom, closestNode, start, target);
}
// 获取瓦片坐标每个瓦片覆盖±0.5范围)
private static Vector2Int GetTileCoord(Vector2 position)
{
return new Vector2Int(
Mathf.RoundToInt(position.x),
Mathf.RoundToInt(position.y)
);
}
// 计算启发式估值(欧几里得距离)
private static float Heuristic(Vector2Int a, Vector2Int b)
{
return Vector2.Distance(
new Vector2(a.x, a.y),
new Vector2(b.x, b.y)
);
}
// 获取移动成本
private static float GetMovementCost(Vector2Int from, Vector2Int to)
{
// 计算基础距离(正交=1对角=√2
var distance = (from.x == to.x || from.y == to.y) ? 1f : 1.4142f;
// 应用目标瓦片的速度削减率
var costModifier = Map.MapGenerator.Instance.GetTilePassCost(to.x, to.y);
// 成本 = 距离 × (1 + 速度削减率)
return distance * (1 + costModifier);
}
// 重建路径
private static List<Vector2> ReconstructPath(
Dictionary<Vector2Int, Vector2Int> cameFrom,
Vector2Int current,
Vector2 start,
Vector2 end)
{
// 构建瓦片路径
var tilePath = new List<Vector2Int>();
tilePath.Add(current);
while (cameFrom.ContainsKey(current))
{
current = cameFrom[current];
tilePath.Add(current);
}
tilePath.Reverse();
// 转换为实际坐标路径
var path = new List<Vector2>();
path.Add(start); // 添加精确起点
// 添加路径点(瓦片中心)
foreach (var tile in tilePath)
{
path.Add(new Vector2(tile.x, tile.y));
}
path.Add(end); // 添加精确终点
return path;
}
}
}

View File

@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: 586ed74166c04dae862f096bdc52f63b
timeCreated: 1754750432

View File

@ -1,5 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<Define>
<ImageDef>
<defName>TestGunItem</defName>
<path>Resources\Item\TestGun.png</path>
</ImageDef>
<ImageDef>
<defName>TestGun</defName>
<path>Resources\Item\TestGunUse.png</path>
</ImageDef>
<ImageDef>
<defName>yellowBullet</defName>
<path>Resources\Item\YellowBullet_down.png</path>
</ImageDef>
<AttributesDef>
<defName>TestGun</defName>
<attack>10</attack>
@ -26,26 +41,23 @@
<moveSpeed>20</moveSpeed>
</attributes>
<drawingOrder>
<texturePath>Resources\Item</texturePath>
<pixelsPerUnit>20</pixelsPerUnit>
<drawingOrder_down>
<node name="YellowBullet"/>
</drawingOrder_down>
<idle_down>
<textures>
<li>yellowBullet</li>
</textures>
</idle_down>
<walk_down>
<textures>
<li>yellowBullet</li>
</textures>
</walk_down>
</drawingOrder>
<behaviorTree>
<Node className="JobGiver_ContinuousMove"/>
</behaviorTree>
</BulletDef>
<ImageDef>
<defName>TestGunItem</defName>
<path>Resources\Item\TestGun.png</path>
</ImageDef>
<ImageDef>
<defName>TestGun</defName>
<path>Resources\Item\TestGunUse.png</path>
</ImageDef>

View File

@ -2,11 +2,17 @@
<Define>
<!-- 贴图部分 -->
<ImageDef>
<defName>testPawn</defName>
<defName>testPawnAnimation</defName>
<path>res:Character/Test/Body/idle_down</path>
<wCount>5</wCount>
<hCount>1</hCount>
</ImageDef>
<ImageDef>
<defName>testPawn</defName>
<path>Resources\Character\test.png</path>
<wCount>4</wCount>
<hCount>4</hCount>
</ImageDef>
<!-- 人物定义 -->
<CharacterDef>
@ -19,15 +25,93 @@
</attributes>
<affiliation>player</affiliation>
<drawingOrder>
<idle_down name="Body" FPS="2">
<animationTextures>
<!-- Idle states -->
<idle_up>
<textures>
<li>testPawn_0</li>
<li>testPawn_1</li>
<li>testPawn_2</li>
<li>testPawn_3</li>
</textures>
</idle_up>
<idle_down>
<textures>
<li>testPawn_4</li>
</animationTextures>
</textures>
</idle_down>
<idle_left>
<textures>
<li>testPawn_8</li>
</textures>
</idle_left>
<idle_right>
<textures>
<li>testPawn_12</li>
</textures>
</idle_right>
<!-- Walk states -->
<walk_up>
<textures>
<li>testPawn_1</li>
</textures>
</walk_up>
<walk_down>
<textures>
<li>testPawn_5</li>
</textures>
</walk_down>
<walk_left>
<textures>
<li>testPawn_9</li>
</textures>
</walk_left>
<walk_right>
<textures>
<li>testPawn_13</li>
</textures>
</walk_right>
<!-- Melee Attack states -->
<meleeAttack_up>
<textures>
<li>testPawn_2</li>
</textures>
</meleeAttack_up>
<meleeAttack_down>
<textures>
<li>testPawn_6</li>
</textures>
</meleeAttack_down>
<meleeAttack_left>
<textures>
<li>testPawn_10</li>
</textures>
</meleeAttack_left>
<meleeAttack_right>
<textures>
<li>testPawn_14</li>
</textures>
</meleeAttack_right>
<!-- Ranged Attack states -->
<rangedAttack_up>
<textures>
<li>testPawn_3</li>
</textures>
</rangedAttack_up>
<rangedAttack_down>
<textures>
<li>testPawn_7</li>
</textures>
</rangedAttack_down>
<rangedAttack_left>
<textures>
<li>testPawn_11</li>
</textures>
</rangedAttack_left>
<rangedAttack_right>
<textures>
<li>testPawn_15</li>
</textures>
</rangedAttack_right>
</drawingOrder>
<behaviorTree>
<Node className="JobGiver_RandomWander"/>
@ -44,10 +128,18 @@
</attributes>
<affiliation>player</affiliation>
<drawingOrder>
<texturePath>res:Character\Test</texturePath>
<drawingOrder_down>
<node name="Body"/>
</drawingOrder_down>
<idle_down name="Body" FPS="4">
<textures>
<li>testPawnAnimation_0</li>
<li>testPawnAnimation_1</li>
<li>testPawnAnimation_2</li>
<li>testPawnAnimation_3</li>
<li>testPawnAnimation_4</li>
<li>testPawnAnimation_3</li>
<li>testPawnAnimation_2</li>
<li>testPawnAnimation_1</li>
</textures>
</idle_down>
</drawingOrder>
<behaviorTree>
<Node className="JobGiver_RandomWander"/>
@ -64,11 +156,18 @@
</attributes>
<affiliation>player</affiliation>
<drawingOrder>
<texturePath>res:Character\HighSpeed</texturePath>
<pixelsPerUnit>200</pixelsPerUnit>
<drawingOrder_down>
<node name="Body"/>
</drawingOrder_down>
<idle_down name="Body" FPS="4">
<textures>
<li>testPawnAnimation_0</li>
<li>testPawnAnimation_1</li>
<li>testPawnAnimation_2</li>
<li>testPawnAnimation_3</li>
<li>testPawnAnimation_4</li>
<li>testPawnAnimation_3</li>
<li>testPawnAnimation_2</li>
<li>testPawnAnimation_1</li>
</textures>
</idle_down>
</drawingOrder>
<behaviorTree>
<Node className="JobGiver_Idel"/>
@ -85,11 +184,18 @@
</attributes>
<affiliation>player</affiliation>
<drawingOrder>
<texturePath>res:Character\HighSpeed</texturePath>
<pixelsPerUnit>200</pixelsPerUnit>
<drawingOrder_down>
<node name="Body" />
</drawingOrder_down>
<idle_down name="Body" FPS="4">
<textures>
<li>testPawnAnimation_0</li>
<li>testPawnAnimation_1</li>
<li>testPawnAnimation_2</li>
<li>testPawnAnimation_3</li>
<li>testPawnAnimation_4</li>
<li>testPawnAnimation_3</li>
<li>testPawnAnimation_2</li>
<li>testPawnAnimation_1</li>
</textures>
</idle_down>
</drawingOrder>
<behaviorTree>
<Node className="JobGiver_Idel"/>

Binary file not shown.

After

Width:  |  Height:  |  Size: 734 B