Unity DXF转Prefab的工具和应用
·
在虚拟仿真软件开发过程中,Unity 需要展示 DXF 文件的内容。此工具可以将 DXF 文件转换为 Prefab,方便在 Unity 中使用。
注:本文只是介绍此工具后续的扩展内容,觉得工具不错的请给工具的作者点Star
工具来源: GitHub - Unity3D DXF Viewer
GitHub工具原示例图:
1. DXF 转换
此部分内容可参考 GitHub 上的工具使用说明,此处不作详细介绍。
2. 移除预制体多余脚本
DXF 转换后生成的 Prefab 可能会携带较多脚本,运行容易引发错误,因此需要手动移除。
以下是一个简单的移除工具示例:
[MenuItem("Tools/Remove Scripts Editor")]
private static void ShowWindow()
{
GetWindow<RemoveScripts>("Remove Scripts");
}
private void OnGUI()
{
if (!GUILayout.Button("Remove Scripts")) return;
if (Selection.activeGameObject != null)
{
RemoveScriptsFromChildren(Selection.activeGameObject);
}
else
{
Debug.LogWarning("Please select a GameObject.");
}
}
private void RemoveScriptsFromChildren(GameObject parent)
{
RemoveComponents<GoLayer>(parent);
RemoveComponents<GoLine>(parent);
RemoveComponents<GoArc>(parent);
RemoveComponents<GoCircle>(parent);
RemoveComponents<GoEllipse>(parent);
RemoveComponents<GoText>(parent);
RemoveComponents<GoInsert>(parent);
RemoveComponents<GoLwpolyLine>(parent);
PrefabUtility.ApplyPrefabInstance(parent, InteractionMode.AutomatedAction);
SceneView.RepaintAll();
Debug.Log("清除完成");
}
private void RemoveComponents<T>(GameObject parent) where T : Component
{
T[] scripts = parent.GetComponentsInChildren<T>();
foreach (var script in scripts)
{
DestroyImmediate(script, true);
}
}
3. 运行时动态修改 Layer 分组的材质颜色
3.1 Layer 分组
在导出 DXF 文件时,需要提前对不同部分进行分组(生成的预制体子物体分散,生成之后再分组工作量巨大),以便在 Unity 中进行材质颜色控制。
3.2 控制某个组的材质颜色(示例:Layer 组挂载Colorful,以便动态更改颜色)
Colorful代码示例:(半透明材质修改部分仅作展示)
public class Colorful : MonoBehaviour
{
public enum Property
{
None = 0,
Color = 1 << 1,
Position = 1 << 2,
Material = 1 << 3,
All = Color | Position | Material
}
[SerializeField] private bool bringToFront = false;
private readonly Dictionary<Material, Color> _rawColorMap = new Dictionary<Material, Color>();
private readonly Dictionary<Transform, Vector3> _rawPosMap = new Dictionary<Transform, Vector3>();
private readonly Dictionary<Renderer, List<Material>> _rendererMap = new Dictionary<Renderer, List<Material>>();
private Color _currentColor = Color.white;
private bool initialized = false;
private bool colorChanged = false;
private bool bringedFront = false;
public void Initialize()
{
_rawColorMap.Clear();
_rawPosMap.Clear();
_rendererMap.Clear();
Stack<GameObject> stack = new Stack<GameObject>();
stack.Push(this.gameObject);
while (stack.Count > 0)
{
GameObject current = stack.Pop();
_rawPosMap.Add(current.transform, current.transform.position);
Renderer r = current.GetComponent<Renderer>();
if (r != null)
{
Material[] materials = r.materials;
_rendererMap.Add(r, new List<Material>(materials));
foreach (var t in materials)
{
_rawColorMap.Add(t, t.color);
}
}
for (int i = current.transform.childCount - 1; i >= 0; --i)
{
stack.Push(current.transform.GetChild(i).gameObject);
}
}
}
public void ChangeColor(Color color, bool exceptAlpha = false)
{
if (!initialized)
{
Initialize();
initialized = true;
}
using (var itr = _rawColorMap.GetEnumerator())
{
while (itr.MoveNext())
{
if (bringToFront)
{
bringedFront = true;
itr.Current.Key.SetFloat("Render Queue", 2002);
}
else
{
bringedFront = false;
}
if (exceptAlpha)
{
float a = itr.Current.Key.color.a;
color.a = a;
}
if (color.a < 1)
{
//此部分内容自定义实现,仅作示例
itr.Current.Key.SetFloat("_Mode", 3);
itr.Current.Key.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha);
itr.Current.Key.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
itr.Current.Key.SetInt("_ZWrite", 1);
itr.Current.Key.DisableKeyword("_ALPHATEST_ON");
itr.Current.Key.EnableKeyword("_ALPHABLEND_ON");
itr.Current.Key.DisableKeyword("_ALPHAPREMULTIPLY_ON");
itr.Current.Key.renderQueue = 3000;
}
itr.Current.Key.color = color;
}
}
_currentColor = color;
colorChanged = true;
}
public void ChangeMaterial(Material mat)
{
if (!initialized)
{
Initialize();
initialized = true;
}
using var itr = _rendererMap.GetEnumerator();
while (itr.MoveNext())
{
Material[] mats = new Material[itr.Current.Value.Count];
for (int i = 0; i < mats.Length; ++i)
{
mats[i] = mat;
}
itr.Current.Key.materials = mats;
}
}
public void ResetColor(Property property = Property.All)
{
if (!initialized)
{
return;
}
if ((property & Property.Color) == Property.Color)
{
using var itr = _rawColorMap.GetEnumerator();
while (itr.MoveNext())
{
if (bringedFront)
{
itr.Current.Key.SetFloat("Render Queue", 2000);
bringedFront = false;
}
itr.Current.Key.color = itr.Current.Value;
//itr.Current.Key.SetColor("_EmissionColor",Color.white);
//itr.Current.Key.DisableKeyword("_EMISSION");
//此部分内容自定义实现,仅作示例
itr.Current.Key.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
itr.Current.Key.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);
itr.Current.Key.SetInt("_ZWrite", 1);
itr.Current.Key.DisableKeyword("_ALPHATEST_ON");
itr.Current.Key.DisableKeyword("_ALPHABLEND_ON");
itr.Current.Key.DisableKeyword("_ALPHAPREMULTIPLY_ON");
itr.Current.Key.renderQueue = 2000;
}
}
if ((property & Property.Position) == Property.Position)
{
using var itr = _rawPosMap.GetEnumerator();
while (itr.MoveNext())
{
itr.Current.Key.position = itr.Current.Value;
}
}
if ((property & Property.Material) == Property.Material)
{
using var itr = _rendererMap.GetEnumerator();
while (itr.MoveNext())
{
itr.Current.Key.materials = itr.Current.Value.ToArray();
}
}
}
};
4. 在 UI 界面内查看生成的Prefab(DXF),并实现拖拽与缩放
4.1 拖拽控制 代码示例
public void DragDraw(BaseEventData e)
{
PointerEventData data = e as PointerEventData;
if (data.button == PointerEventData.InputButton.Middle)
{
Camera renderCamera = m_drawRenderer.renderCamera;
Transform trans = renderCamera.transform;
Vector3 delta = new Vector3(-data.delta.x, -data.delta.y) * renderCamera.orthographicSize * dragSpeed;
trans.Translate(delta, Space.World);
}
}
4.2 缩放控制 代码示例(基于鼠标位置、需要注意RawImage的锚点设置)
public void ScrollDraw(BaseEventData e)
{
PointerEventData data = e as PointerEventData;
Camera renderCamera = m_drawRenderer.renderCamera;
var aspectRatio = m_rawImage.texture.width / (float)m_rawImage.texture.height;//获得宽高的缩放比
var orthographicSize = renderCamera.orthographicSize;
float scaleSize = orthographicSize;//暂存相机的初始 orthographicSize
if (data != null) orthographicSize -= (data.scrollDelta.y * orthographicSize * zoomSpeed);
renderCamera.orthographicSize = orthographicSize;
scaleSize = orthographicSize - scaleSize;//得到缩放的大小
//注意:RawImage的锚点需要居中
if (RectTransformUtility.ScreenPointToLocalPointInRectangle(m_rawImage.rectTransform, Input.mousePosition,
null, out var localPoint))//得到鼠标在RawImage上映射的坐标值【RawImage中心点(描点)的坐标为(0,0)】
{
Vector2 rectSize = m_rawImage.rectTransform.rect.size;
rectSize *= 0.5f;
//鼠标相对RawImage中心点的偏移距离除以RawImage的宽高和乘以宽高缩放比 计算出摄像机需要移动的X、Y值
Vector2 moveScale = new Vector2((localPoint.x / rectSize.x) * aspectRatio, localPoint.y / rectSize.y);
moveScale *= -scaleSize;
renderCamera.transform.position += new Vector3(moveScale.x, moveScale.y, 0);
}
}
结论
使用该工具可以方便地在 Unity 中显示 DXF 文件,并支持动态修改颜色、材质以及在 UI 中实现拖拽和缩放操作。希望本文对你的开发有所帮助!
更多推荐
所有评论(0)