简单的贴花系统只能在编辑器中工作
Simple decal system only working in editor
我开发网络播放器应用程序。
在场景中我有一些 3d 模型(例如:盒子)。
在运行时,我上传 *.png 图像并在 Decal 上使用此图像到我的车上。
我使用这个包:https://www.assetstore.unity3d.com/en/#!/content/13889 用于贴花系统。
我的编辑器工作正常,但在运行时我不能在贴花系统中使用我的图片。
任务:需要随时更换图片,在Decal System中成为一个好东西。
请帮我。
谢谢!
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;
}
}
我明白了。谢谢大家!
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();
}
我决定在@NoIQ 的回答的基础上创建一些更便携的东西:
using UnityEngine;
using System.Collections.Generic;
/*
*/
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();
}
}
要使用,需要将Editor文件夹中的脚本移动到父目录下。以下是我如何使用脚本添加动态枪支贴花:
GameObject decal = Instantiate(prefab, col.contacts[0].point, Quaternion.Euler(col.contacts[0].normal));
DecalDynamic.BuildDecal(decal.GetComponent<Decal>());
从以下 link 或通过 Unity Asset Store 将免费资源 'Basic Decal System' 导入 Unity。
https://assetstore.unity.com/packages/tools/particles-effects/simple-decal-system-13889
如果需要,为贴花准备一张合适的透明图片。将文件保存为 TARGA (.tga) 格式并导入到 Unity 中合适的位置。
*** 注意。创建一个包含 sheet 个用作贴花的图像的图像文件会更整洁。
从图像创建精灵
Select Assets 和 inspector 中的图像文件将 Texture type 更改为 Sprite(2D and UI) 并按下 apply。
如果图像文件只包含一张图像,来自检查器,select Sprite 模式为 Single。如果您已经创建了 sheet 个图像然后 select 多个,那么您可以 select 'Sprite Editor' 并通过在 sheet 上的每个图像周围绘制边界来创建多个精灵图像并提供合适的名称。精灵会飞出原图。
创建 Material
创建一个新的 material。那么 material 的名称必须以 'Decal' 开头。在检查器中,将着色器更改为 'Legacy Shaders/Transparency/Diffuse',然后单击 'Select' 和 select 包含精灵的图像。
创建贴花
在场景中创建一个 Cube,重命名为合适的名称,然后从 Assets>DecalSystem>Plugins>Decalsystem,将脚本 'Decal' 拖放到 Cube 上。立方体现在将是线框外观。从 Decal Script 部分的检查器中,Select 之前创建的 material 然后 select 下拉列表中的精灵。
将立方体放在要投影的网格上(您可能必须旋转立方体以对齐投影面)。
贴花不会在运行时呈现。要使贴花渲染,请执行以下步骤。
创建一个空的游戏对象并将其重命名为带有 'Pos' 后缀的贴花。 select 贴花立方体对象,然后单击检查器变换部分中的设置图标并复制组件。 Select 空游戏对象,然后单击检查器变换部分中的设置图标并粘贴组件值,然后将 xyz 比例值更改为“1”。在层次结构中,将贴花立方体对象放到空位置对象上。
Select 空位置对象并从检查器中单击添加组件和 select 'Decal_Script' 脚本。 Decal_Script
在检查器中,将 Decal Cube 对象拖动(或 select 从右侧的按钮)到 '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);
}
}
}
我开发网络播放器应用程序。 在场景中我有一些 3d 模型(例如:盒子)。 在运行时,我上传 *.png 图像并在 Decal 上使用此图像到我的车上。 我使用这个包:https://www.assetstore.unity3d.com/en/#!/content/13889 用于贴花系统。 我的编辑器工作正常,但在运行时我不能在贴花系统中使用我的图片。 任务:需要随时更换图片,在Decal System中成为一个好东西。 请帮我。 谢谢!
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;
}
}
我明白了。谢谢大家!
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();
}
我决定在@NoIQ 的回答的基础上创建一些更便携的东西:
using UnityEngine;
using System.Collections.Generic;
/*
*/
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();
}
}
要使用,需要将Editor文件夹中的脚本移动到父目录下。以下是我如何使用脚本添加动态枪支贴花:
GameObject decal = Instantiate(prefab, col.contacts[0].point, Quaternion.Euler(col.contacts[0].normal));
DecalDynamic.BuildDecal(decal.GetComponent<Decal>());
从以下 link 或通过 Unity Asset Store 将免费资源 'Basic Decal System' 导入 Unity。
https://assetstore.unity.com/packages/tools/particles-effects/simple-decal-system-13889
如果需要,为贴花准备一张合适的透明图片。将文件保存为 TARGA (.tga) 格式并导入到 Unity 中合适的位置。
*** 注意。创建一个包含 sheet 个用作贴花的图像的图像文件会更整洁。
从图像创建精灵 Select Assets 和 inspector 中的图像文件将 Texture type 更改为 Sprite(2D and UI) 并按下 apply。
如果图像文件只包含一张图像,来自检查器,select Sprite 模式为 Single。如果您已经创建了 sheet 个图像然后 select 多个,那么您可以 select 'Sprite Editor' 并通过在 sheet 上的每个图像周围绘制边界来创建多个精灵图像并提供合适的名称。精灵会飞出原图。
创建 Material 创建一个新的 material。那么 material 的名称必须以 'Decal' 开头。在检查器中,将着色器更改为 'Legacy Shaders/Transparency/Diffuse',然后单击 'Select' 和 select 包含精灵的图像。
创建贴花 在场景中创建一个 Cube,重命名为合适的名称,然后从 Assets>DecalSystem>Plugins>Decalsystem,将脚本 'Decal' 拖放到 Cube 上。立方体现在将是线框外观。从 Decal Script 部分的检查器中,Select 之前创建的 material 然后 select 下拉列表中的精灵。
将立方体放在要投影的网格上(您可能必须旋转立方体以对齐投影面)。
贴花不会在运行时呈现。要使贴花渲染,请执行以下步骤。
创建一个空的游戏对象并将其重命名为带有 'Pos' 后缀的贴花。 select 贴花立方体对象,然后单击检查器变换部分中的设置图标并复制组件。 Select 空游戏对象,然后单击检查器变换部分中的设置图标并粘贴组件值,然后将 xyz 比例值更改为“1”。在层次结构中,将贴花立方体对象放到空位置对象上。
Select 空位置对象并从检查器中单击添加组件和 select 'Decal_Script' 脚本。 Decal_Script
在检查器中,将 Decal Cube 对象拖动(或 select 从右侧的按钮)到 '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);
}
}
}