Unity定位与Update在功能上的不同
Unity Position Different in Function Compared to Update
在这段代码中,当我试图获得 transform.position
或 _attackPoint.position
时。该值始终为 (0,0,0),但是当我在 Update 方法中进行转换时,它打印正常。
public class MeleeWeapon : Weapon
{
[SerializeField] private Transform _attackPoint;
[SerializeField] private float _attackRange;
[SerializeField] private LayerMask _enemyLayers;
private void Update()
{
Debug.Log(transform.position); // Prints right
}
public override void Attack()
{
Debug.Log(transform.position); // Prints 0,0,0
Collider2D[] hitEnemies = Physics2D.OverlapCircleAll(_attackPoint.position, _attackRange, _enemyLayers);
Debug.Assert(hitEnemies.Length > 0); // Assertion failed
foreach(Collider2D enemy in hitEnemies)
{
Debug.Log($"We hit {enemy.name}");
CharacterStats stats = enemy.GetComponent<CharacterStats>();
if (stats == null) continue;
stats.ApplyDamage(damage);
}
}
}
Game View
我正在像下面那样实例化 MeleeWeapon
foreach (PivotToTransform pivot in pivotPoints)
{
if (pivot.slot == item.initialSlot)
{
// Instantiate prefab
GameObject it = Instantiate(item.prefab, pivot.point.position, Quaternion.identity);
if (!item.isDisposable) // If item not disposable set parent transform
it.transform.SetParent(pivot.point);
// Set current prefab
_currentPrefab = it;
}
}
这里是支点:
Pivot Points
这是 MeleeWeapon 预制件:
MeleeWeapon Prefab
我用
攻击
try
{
var equippedItems = EquipmentManager.Instance.equippedItems;
var selectedSlot = EquipmentManager.Instance.selectedSlot;
if (equippedItems.ContainsKey(selectedSlot))
{
// Try to get weapon
Item equippedItem = equippedItems[selectedSlot];
Weapon weapon = equippedItem.prefab.GetComponent<Weapon>();
if (weapon == null) throw new System.Exception();
// Actualy attack
weapon.Attack();
if (equippedItem.isDisposable)
{
RemoveState state = Inventory.Instance.RemoveItem(equippedItem, 1);
// Unequip item if removed
switch (state)
{
case RemoveState.Removed:
EquipmentManager.Instance.UnEquip(equippedItem.initialSlot);
break;
case RemoveState.Error:
throw new System.Exception();
}
}
// Set cooldown
sm.StartCoroutine(Cooldown(equippedItem.cooldown));
}
else
{
sm.ChangeState(sm.IdleState);
}
}
catch (System.Exception)
{
sm.ChangeState(sm.IdleState);
}
您尝试过使用 transform.localPosition 吗?
gameObject 的父对象可能会导致这种情况。
看来育儿方面没什么问题。当我尝试攻击时,我使用的是未实例化的预制件。我像这样更改了攻击脚本并解决了。
EquipmentManager.Instance.currentPrefab.GetComponent<MeleeWeapon>().Attack();
您正在呼叫:
Weapon weapon = equippedItem.prefab.GetComponent<Weapon>();
当我读到这篇文章时,您似乎得到的是 PREFAB 而不是 INSTANCE。为什么不直接从 Item
中检索 Weapon
脚本?你得到:
Item equippedItem = equippedItems[selectedSlot];
而且我认为你需要从 equippedItem
而不是预制件上取下武器:
Weapon weapon = equippedItem.GetComponent<Weapon>();
当您从预制件中获取脚本时,您将获得一个未从尚未实例化的游戏对象中激活的脚本。
在这段代码中,当我试图获得 transform.position
或 _attackPoint.position
时。该值始终为 (0,0,0),但是当我在 Update 方法中进行转换时,它打印正常。
public class MeleeWeapon : Weapon
{
[SerializeField] private Transform _attackPoint;
[SerializeField] private float _attackRange;
[SerializeField] private LayerMask _enemyLayers;
private void Update()
{
Debug.Log(transform.position); // Prints right
}
public override void Attack()
{
Debug.Log(transform.position); // Prints 0,0,0
Collider2D[] hitEnemies = Physics2D.OverlapCircleAll(_attackPoint.position, _attackRange, _enemyLayers);
Debug.Assert(hitEnemies.Length > 0); // Assertion failed
foreach(Collider2D enemy in hitEnemies)
{
Debug.Log($"We hit {enemy.name}");
CharacterStats stats = enemy.GetComponent<CharacterStats>();
if (stats == null) continue;
stats.ApplyDamage(damage);
}
}
}
Game View
我正在像下面那样实例化 MeleeWeapon
foreach (PivotToTransform pivot in pivotPoints)
{
if (pivot.slot == item.initialSlot)
{
// Instantiate prefab
GameObject it = Instantiate(item.prefab, pivot.point.position, Quaternion.identity);
if (!item.isDisposable) // If item not disposable set parent transform
it.transform.SetParent(pivot.point);
// Set current prefab
_currentPrefab = it;
}
}
这里是支点:
Pivot Points
这是 MeleeWeapon 预制件:
MeleeWeapon Prefab
我用
攻击try
{
var equippedItems = EquipmentManager.Instance.equippedItems;
var selectedSlot = EquipmentManager.Instance.selectedSlot;
if (equippedItems.ContainsKey(selectedSlot))
{
// Try to get weapon
Item equippedItem = equippedItems[selectedSlot];
Weapon weapon = equippedItem.prefab.GetComponent<Weapon>();
if (weapon == null) throw new System.Exception();
// Actualy attack
weapon.Attack();
if (equippedItem.isDisposable)
{
RemoveState state = Inventory.Instance.RemoveItem(equippedItem, 1);
// Unequip item if removed
switch (state)
{
case RemoveState.Removed:
EquipmentManager.Instance.UnEquip(equippedItem.initialSlot);
break;
case RemoveState.Error:
throw new System.Exception();
}
}
// Set cooldown
sm.StartCoroutine(Cooldown(equippedItem.cooldown));
}
else
{
sm.ChangeState(sm.IdleState);
}
}
catch (System.Exception)
{
sm.ChangeState(sm.IdleState);
}
您尝试过使用 transform.localPosition 吗?
gameObject 的父对象可能会导致这种情况。
看来育儿方面没什么问题。当我尝试攻击时,我使用的是未实例化的预制件。我像这样更改了攻击脚本并解决了。
EquipmentManager.Instance.currentPrefab.GetComponent<MeleeWeapon>().Attack();
您正在呼叫:
Weapon weapon = equippedItem.prefab.GetComponent<Weapon>();
当我读到这篇文章时,您似乎得到的是 PREFAB 而不是 INSTANCE。为什么不直接从 Item
中检索 Weapon
脚本?你得到:
Item equippedItem = equippedItems[selectedSlot];
而且我认为你需要从 equippedItem
而不是预制件上取下武器:
Weapon weapon = equippedItem.GetComponent<Weapon>();
当您从预制件中获取脚本时,您将获得一个未从尚未实例化的游戏对象中激活的脚本。