【问题标题】:Simple decal system only working in editor仅在编辑器中工作的简单贴花系统
【发布时间】:2015-02-18 16:42:35
【问题描述】:

我开发 Web Player 应用程序。 在场景中我有一些 3d 模型(例如:盒子)。 在运行时,我上传 *.png 图像并在贴花上使用此图像到我的汽车。 我使用这个包:https://www.assetstore.unity3d.com/en/#!/content/13889 用于贴花系统。 我的编辑器工作正常,但在运行时我无法在贴花系统中使用我的图片。 任务:需要随时更换一张图片,并成为贴花系统中的好东西。 请帮我。 谢谢!

public GameObject decal;
public Material mat;
Texture2D texTmp;
Sprite spr;
string settingsContent;
string[] settingsSplit;

int texWidth,texHeight;

void Awake()
{
    StartCoroutine(DownloadSettings());
}

IEnumerator DownloadSettings()
{
    WWW www = new WWW("http://585649.workwork.web.hosting-test.net/Logo1/settings.txt");
    yield return www;
    settingsContent = www.text;
    settingsSplit = settingsContent.Split('\n');
    if (www.isDone)
    {
        texWidth = int.Parse(settingsSplit[1]);
        texHeight = int.Parse(settingsSplit[2]);
        texTmp = new Texture2D(texWidth,texHeight);
        StartCoroutine(DownloadLogos());
    }
}

IEnumerator DownloadLogos()
{
    WWW www = new WWW(settingsSplit[0]);
    yield return www;
    www.LoadImageIntoTexture(texTmp);
    if (www.isDone)
    {
        spr = Sprite.Create(texTmp, new Rect(0, 0, texTmp.width, texTmp.height), Vector2.zero, 100);
        spr.texture.wrapMode = TextureWrapMode.Clamp;
        mat.mainTexture = spr.texture;
        Color clr = new Color32(255,255,255,255);
        clr.a = float.Parse(settingsSplit[3]);
        mat.color = clr;
        decal.AddComponent("Decal");
        decal.GetComponent<Decal>().material = mat;
        decal.GetComponent<Decal>().sprite = spr;
    }
}

【问题讨论】:

  • 我编辑我的问题(带代码)

标签: c# unity3d assets


【解决方案1】:

我明白了。谢谢大家!

public Decal decal;
public Material mat;
Texture2D texTmp;
Sprite spr;
string settingsContent;
string[] settingsSplit;

int texWidth,texHeight;
float sizeX, sizeY;

void Awake()
{
    StartCoroutine(DownloadSettings());
}

IEnumerator DownloadSettings()
{
    WWW www = new WWW("http://sitesman.com/logotypes/Logo1/settings.txt");
    yield return www;
    settingsContent = www.text;
    settingsSplit = settingsContent.Split('\n');
    if (www.isDone)
    {
        texWidth = int.Parse(settingsSplit[1]);
        texHeight = int.Parse(settingsSplit[2]);
        texTmp = new Texture2D(texWidth,texHeight);

        if(texWidth > texHeight)
        {
            sizeX = texWidth / texHeight;
            sizeY = 1;
        }
        else if (texWidth < texHeight)
        {
            sizeX = 1;
            sizeY = texHeight / texWidth;
        }
        else
        {
            sizeX = 1;
            sizeY = 1;
        }

        float multipier = 1;

        if(settingsSplit[4] != null)
        {
            multipier = float.Parse(settingsSplit[4]);
        }

        decal.transform.localScale = new Vector3(sizeX*multipier,sizeY*multipier,2f);

        StartCoroutine(DownloadLogos());
    }
}

IEnumerator DownloadLogos()
{
    WWW www = new WWW(settingsSplit[0]);
    yield return www;
    www.LoadImageIntoTexture(texTmp);
    if (www.isDone)
    {
        spr = Sprite.Create(texTmp, new Rect(0, 0, texTmp.width, texTmp.height), Vector2.zero, 100);
        spr.texture.wrapMode = TextureWrapMode.Clamp;
        mat.mainTexture = spr.texture;
        Color clr = new Color32(255,255,255,255);
        clr.a = float.Parse(settingsSplit[3]);
        mat.color = clr;
        decal.material = mat;
        decal.sprite = spr;
        BuildDecal(decal);
    }
}

GameObject go;
private GameObject[] affectedObjects;

private void BuildDecal(Decal decal)
{
    MeshFilter filter = decal.GetComponent<MeshFilter>();
    if (filter == null) filter = decal.gameObject.AddComponent<MeshFilter>();
    if (decal.renderer == null) decal.gameObject.AddComponent<MeshRenderer>();
    decal.renderer.material = decal.material;

    if (decal.material == null || decal.sprite == null)
    {
        filter.mesh = null;
        return;
    }

    affectedObjects = GetAffectedObjects(decal.GetBounds(), decal.affectedLayers);
    foreach (GameObject go in affectedObjects)
    {
        DecalBuilder.BuildDecalForObject(decal, go);
    }
    DecalBuilder.Push(decal.pushDistance);

    Mesh mesh = DecalBuilder.CreateMesh();
    if (mesh != null)
    {
        mesh.name = "DecalMesh";
        filter.mesh = mesh;
    }
}

private static GameObject[] GetAffectedObjects(Bounds bounds, LayerMask affectedLayers)
{
    MeshRenderer[] renderers = (MeshRenderer[])GameObject.FindObjectsOfType<MeshRenderer>();
    List<GameObject> objects = new List<GameObject>();
    foreach (Renderer r in renderers)
    {
        if (!r.enabled) continue;
       // if (!IsLayerContains(affectedLayers, r.gameObject.layer)) continue;
        if (r.GetComponent<Decal>() != null) continue;

        if (bounds.Intersects(r.bounds))
        {
            objects.Add(r.gameObject);
        }
    }
    return objects.ToArray();
}

【讨论】:

    【解决方案2】:

    通过以下链接或通过 Unity 资源商店将免费资源“基本贴花系统”导入 Unity。

    https://assetstore.unity.com/packages/tools/particles-effects/simple-decal-system-13889

    如果需要,请为具有透明度的贴花准备合适的图像。将文件保存为 TARGA (.tga) 格式,然后在合适的位置导入 Unity。

    *** 注意。创建一个包含一张图像用作贴花的图像文件会更简洁。

    从图像创建精灵 在 Assets 中选择图像文件,在检查器中将 Texture 类型更改为 Sprite(2D 和 UI),然后按 apply。

    如果图像文件仅包含一张图像,则从检查器中选择“Single”作为精灵模式。如果您已经创建了一张图像然后选择多个,然后您可以选择“Sprite Editor”并通过在图像张上的每个图像周围绘制边界并提供合适的名称来创建多个精灵。精灵将出现在原始图像下方。

    创建材质 创建新材料。然后材料的名称必须以“贴花”开头。在检查器中,将着色器更改为“Legacy Shaders/Transparency/Diffuse”,然后单击“选择”并选择包含精灵的图像。

    创建贴花 在场景中创建一个 Cube,重命名为合适的名称,然后从 Assets>DecalSystem>Plugins>Decalsystem 将脚本“Decal”拖放到 Cube 上。立方体现在将是线框外观。在 Decal Script 部分的检查器中,选择之前创建的材质,然后从下拉列表中选择 sprite。

    将立方体放在要投影的网格上(您可能需要旋转立方体以对齐投影面)。

    贴花不会在运行时渲染。要渲染贴花,请按照以下步骤操作。

    创建一个空的游戏对象并将其与贴花相关的名称重命名为“Pos”后缀。选择贴花立方体对象,然后单击检查器转换部分中的设置图标并复制组件。选择空的游戏对象,然后单击检查器变换部分中的设置图标并粘贴组件值,然后将 xyz 比例值更改为“1”。在层次结构中,将贴花立方体对象拖放到空位置对象上。

    选择空位置对象并从检查器中单击添加组件并选择“Decal_Script”脚本。 Decal_Script

    在检查器中,将 Decal Cube 对象拖动(或从右侧的按钮中选择)到“This Decal”框。

    贴花现在应该在运行时出现。

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using DecalSystem;
    
    public class Decal_Script : MonoBehaviour
    {
       public GameObject ThisDecal;
    
        // Start is called before the first frame update
        void Start()
        {
    
             CreatePrefab();
    
        }
    
        // Update is called once per frame
        void Update()
        {
    
        }
    
        void CreatePrefab()
        {
           // instantiate decal
    
            GameObject obj = Instantiate(ThisDecal, ThisDecal.transform.position, ThisDecal.transform.rotation);
    
            //decal implementation!!
            var decal = obj.GetComponent<Decal>();
            if (decal) //if this obj has decal script
            {
                var filter = decal.GetComponent<MeshFilter>();
                var mesh = filter.mesh;
                if (mesh != null)
                {
                    mesh.name = "DecalMesh";
                    filter.mesh = mesh;
                }
                DecalBuilder.Build(decal);
    
            }
    
       }
    }
    

    【讨论】:

      【解决方案3】:

      我决定在@NoIQ 的回答的基础上创建一些更便携的东西:

      using UnityEngine;
      using System.Collections.Generic;
      
      /*
        http://stackoverflow.com/a/28603035/3990396
      */
      public class DecalDynamic {
          public static void BuildDecal(Decal decal) {
              MeshFilter filter = decal.GetComponent<MeshFilter>();
              if (filter == null) filter = decal.gameObject.AddComponent<MeshFilter>();
              if (decal.GetComponent<Renderer>() == null) decal.gameObject.AddComponent<MeshRenderer>();
              decal.GetComponent<Renderer>().material = decal.material;
      
              if (decal.material == null || decal.sprite == null) {
                  filter.mesh = null;
                  return;
              }
      
              GameObject[] affectedObjects = GetAffectedObjects(decal.GetBounds(), decal.affectedLayers);
              foreach (GameObject go in affectedObjects) {
                  DecalBuilder.BuildDecalForObject(decal, go);
              }
              DecalBuilder.Push(decal.pushDistance);
      
              Mesh mesh = DecalBuilder.CreateMesh();
              if (mesh != null) {
                  mesh.name = "DecalMesh";
                  filter.mesh = mesh;
              }
          }
      
          public static GameObject[] GetAffectedObjects(Bounds bounds, LayerMask affectedLayers) {
              MeshRenderer[] renderers = (MeshRenderer[])GameObject.FindObjectsOfType<MeshRenderer>();
              List<GameObject> objects = new List<GameObject>();
      
              foreach (Renderer r in renderers) {
                  if (!r.enabled || r.GetComponent<Decal>() != null) continue;
                  if (bounds.Intersects(r.bounds)) objects.Add(r.gameObject);
              }
              return objects.ToArray();
          }
      }
      

      要使用,您需要将编辑器文件夹中的脚本移动到父目录。下面是我如何使用脚本添加动态枪贴花:

      GameObject decal = Instantiate(prefab, col.contacts[0].point, Quaternion.Euler(col.contacts[0].normal));
      DecalDynamic.BuildDecal(decal.GetComponent<Decal>());
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-06-20
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多