背景:想实现鼠标点击生成贴花(Decal)在游戏对象表面,可以贴图改变大小,能拖动改变位置
实现方法
设置一个层为CarBody作为贴图附着层,Decal作为贴图层
游戏场景挂载以下代码:
using UnityEngine.UI;
using UnityEngine.EventSystems;
using UnityEngine.Rendering.Universal;
using DG.Tweening;
using UnityEditor;
using System.Drawing;
public class DecalStyleChange : MonoBehaviour
{
[SerializeField]
private Shader shaderGraph; //引擎自带的Decal shadergraph
Texture png = null;
GameObject decal;
GameObject temp,temp2;//记录要移动的物体和缩放的物体
CanvasGroup cg, sl;
bool isMouseButtonDown = false;
public bool isActive = false;
public Slider slider;
[SerializeField]
LayerMask targetLayer;
[SerializeField]
LayerMask ignoreLayer;
void Start()
{
targetLayer = LayerMask.GetMask("CarBody");//根据Layer层判断
ignoreLayer = LayerMask.GetMask("Decal");
cg = GetComponent<CanvasGroup>();
sl = slider.transform.parent.gameOject.GetComponent<CanvasGroup>();//滑动条的父对象挂载CanvasGroup控制透明度
}
void Update()
{
if(Input.GetMouseButtonDown(0) && isActive && !EventSystem.current.IsPointerOverGameObject()) //检测鼠标左键点击
{
StartDrag();
}
if(Input.GetMouseButtonUp(0) && isActive)
{
isMouseButtonDown = false;
temp = null;
}
if(isMouseButtonDown && isActive)
{
isDragging();
}
}
void StartDrag()
{
isMouseButtonDown = true;
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if(Physics.Raycast(ray, out hit, Mathf.Infinity, ignoreLayer))
{
temp = hit.collider.gameObject;//赋值选中的物体
temp2 = temp;
}
else if(Physics.Raycast(ray, out hit, Mathf.Infinity, targetLayer))
{
Quaternion angleOffset = Quaternion.LookRotation(-hit.normal);
CreateDecalProjector(hit.point, angleOffset);//选中位置生成贴图
}
}
void isDragging()//拖拽过程
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if(Physics.Raycast(ray, out hit, Mathf.Infinity, tagetLayer) && temp!=null)//射线击中指定层,并且选中的物体不为空
{
temp.transform.position = hit.point;
temp.transform.localRotation = Quaternion.LookRotation(-hit.normal);//物体Z轴方向 指向 击中点法向
}
}
public void SilderValueChange()//控制贴图大小,挂载在滑动条事件上
{
if(temp2!=null)
{
DecalProjector dec = temp2.GetComponent<DecalProject>();
temp2.transform.localScale = Vector3.one * slider.value;
}
}
public void ActiveDecal()
{
isActive = !isActive;
if(isActive)
{
cg.blocksRaycasts = true;
cg.DOFade(1f,0.5f);
sl.blocksRaycasts = true;
sl.DOFade(1f,0.5f);
}
else
{
cg.blocksRaycasts = false;
cg.DOFade(0f,0.5f);
sl.blocksRaycasts = false;
sl.DOFade(0f,0.5f);
}
}
public void SelectDecal()
{
if(isActive)
{
GameObject selectedObject = EventSystem.current.currentSelectedGameObject;
if(selectedObject.TryGetComponent<Button>(out Button ButtonComponent))
{
png = ButtonComponent.GetComponent<Image>().sprite.texture;
}
}
}
GameObject CreateDecalProjector(Vector3 pos, Quaternion angle)
{
decal = new GameObject("DecalProject");
var decalProjector = decal.AddComponent<DecalProjector>();
decalProjector.scaleMode = DecalScaleMode.InheritFromHierarchy;
decalProjcetor.size = new Vector3(1f, 1f, 0.2f);
decalProjector.pivot = new Vector3(0, 0, 0);
var boxCollider = decal.AddComponent<BoxCollider>();
boxCollider.size = new Vector3(1f, 1f, 0.2f);
boxCollider.center = new Vector3(0, 0, 0);
//设置材质
Material newMat = new Material(shaderGraph);
newMat.SetTexture("Base_Map",png);
newMat.SetFloat("Normal_Blend", 0);
decal.GetComponent<DecalProjector>().material = newMat;
decal.transform.position = pos;
decal.transform.rotation = angle;
decal.layer = LayerMask.NameToLayer("Decal");
return decal;
}
}
存在问题
贴图会附着在第一个物体和第二个物体,只能减少decal的厚度尽量显示在第一个物体上
9627

被折叠的 条评论
为什么被折叠?



