提问人:George Rees 提问时间:11/16/2023 最后编辑:George Rees 更新时间:11/16/2023 访问量:54
与另一个对象处于相同位置的对象具有不同的转换位置
Object in the same position as another object has a different transform position
问:
我有一些从搅拌机导入的对象,因为我试图制作一个基于破坏的游戏,其中一旦被击中的对象将被停用并替换为其损坏/可折叠的对应物。我遇到的问题是,当脚本停用“together”对象并激活“损坏”对象时,它应该具有完全相同的转换位置。然而,一旦“破碎”的物体被激活,它就处于错误的位置。在 Unity 中检查对象时,它们处于相同的位置,但对象的变换位置不同:
下面是我从这里获取的脚本,我只是修改了它,以便当“Snowball”对象命中时,它将触发“一起”和“损坏”对象之间的交换。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Destruction : MonoBehaviour {
[Header("Game Objects")]
[Space(2)]
[Tooltip("The broken gameObject")]
public GameObject brokenObj; // Set to igloo_broken_a object
[Tooltip("The unbroken gameObject")]
public GameObject togetherObj; // Set to Sphere_cell_A objcet
//private Rigidbody togetherObjRb;
[Space(7)]
[Header("State")]
[Space(2)]
[Tooltip("Whether the object is unbroken")]
public bool together = true;
[Tooltip("Whether the object starts broken")]
public bool startBroken = false;
[Space(7)]
[Header("Breaking on Collision")]
[Space(2)]
[Tooltip("Whether the object breaks when it collides with something")]
public bool breakOnCollision = true;
[Tooltip("The minimum relative velocity to break the object")]
public float velocityToBreak = 1; // Velocity required to break object
[Space(7)]
[Header("Breaking when nothing underneath")]
[Space(2)]
[Tooltip("Whether the object breaks when there's nothing underneath supporting it")]
public bool breakOnNoSupports = false;
[Tooltip("The length of the raycast used to check for supports underneath")]
public float raycastLength = 1f;
[Space(7)]
[Header("Sound On Break")]
[Space(2)]
[Tooltip("Whether the object makes a sound when it breaks")]
public bool soundOnBreak = false;
[Tooltip("An array of sounds for the object to make when it breaks (A random one will be selected)")]
public AudioClip[] clips;
[Space(7)]
[Header("Particles On Break")]
[Space(2)]
[Tooltip("Whether the object makes particles when it breaks")]
public bool particlesOnBreak = false;
//Private vars
private AudioSource src;
private ParticleSystem psys;
/* [SerializeField] private float offsetX =41.807335f;
[SerializeField] private float offsetY = 10.52f;
[SerializeField] private float offsetZ = 28.67086f;
*/
void Start () {
//Make sure the right object is active
togetherObj.SetActive(!startBroken);
brokenObj.SetActive(startBroken);
together = !startBroken;
//togetherObjRb = togetherObj.GetComponent<Rigidbody>();
// togetherObjRb.useGravity = false;
if (soundOnBreak)
SetupSound();
if (particlesOnBreak)
SetupParticles();
}
void SetupSound() {
//Get the audio source or create one
src = brokenObj.GetComponent<AudioSource>();
if (src == null)
src = brokenObj.AddComponent<AudioSource>();
//Add a random audio clip to it
src.clip = clips[Random.Range(0, clips.Length-1)];
}
void SetupParticles() {
// Get the particle system or create one
psys = brokenObj.GetComponent<ParticleSystem>();
if (psys == null)
psys = brokenObj.AddComponent<ParticleSystem>();
//This doesn't seem to do anything b/c the gameobject is not active
psys.Stop();
}
void Update () {
/* Broken object should follow unbroken one to prevent them from
* being in the wrong place when they switch */
brokenObj.transform.position = togetherObj.transform.position;
//brokenObj.transform.position = new Vector3(togetherObj.transform.position.x-offsetX , togetherObj.transform.position.y-offsetY,togetherObj.transform.position.z+offsetZ);
Debug.Log("Broken transform: "+brokenObj.transform.position);
Debug.Log("Together transform: "+togetherObj.transform.position);
//Make sure the right object is active
togetherObj.SetActive(together);
brokenObj.SetActive(!together);
if (breakOnNoSupports)
CheckForSupports();
}
void CheckForSupports () {
//Check downwards for supports
if (!Physics.Raycast(transform.position, Vector3.down, raycastLength))
Break();
}
void OnCollisionEnter(Collision collision) {
if (!breakOnCollision)
return;
//Only break if relative velocity is high enough
//if (collision.relativeVelocity.magnitude > velocityToBreak && collision.gameObject.name != "Cylinder" && collision.gameObject.CompareTag("Snowball")){
if (collision.relativeVelocity.magnitude > velocityToBreak && collision.gameObject.name != "Cylinder"){
//togetherObj.SetActive(false);
Break();
}
}
public void Break () {
together = false;
//Play the sound
if (soundOnBreak)
src.Play();
//Show particles
if (particlesOnBreak)
psys.Play();
}
public void BreakWithExplosiveForce(float force, float radius = 3) {
Break();
//Add the explosive force to each rigidbody
foreach (Rigidbody rigid in brokenObj.GetComponentsInChildren<Rigidbody>())
rigid.AddExplosionForce(force, transform.position, radius);
}
}
因此,在玩游戏时,脚本由碰撞触发,“broken”对象与“together”对象处于不同的转换位置:
我尝试过的事情:
答:
从层次结构窗口中可以清楚地看出,这两个对象要么位于同一父对象的根对象,要么位于同一父对象的子对象,因此由于世界位置或局部位置而出现问题的可能性很小。
既然你说网格是从搅拌机导入的,那么这似乎是网格的“几何起源”问题。就像我在搅拌机中设计了这两个立方体一样,一个在中心有原点,另一个在顶点之一。
因此,当我将它们导入 Unity 时,尽管它们出现在场景中的相同位置,但它们的原点位置是不同的,就像您的情况一样。
通过将中心选项更改为枢轴,您将能够看到模型的真实原点位置。
此外,从 Blender 导出模型时,上轴和前轴配置似乎存在一些问题,这从变换线的方向和图像中模型的旋转中可以看出。
顺便说一句,请忽略 100 的比例,我为 UE5 制作一些模型后忘记在 blender 中重置比例。
评论
该问题是由于 blender 中的对象来源造成的。进入搅拌机,然后按 ALT+G 然后单独导出每个破损的碎片后,对象的中心点被校正。
现在转换工作正常,它实际上在以下情况下执行了销毁行为:
下一个:自动控制自行车的旋转
评论
Center
Pivot