2018-01-16 18:39:55 linian71 阅读数 711
  • Unity 值得看的500+ 技术内容列表

    Unity3D是由Unity Technologies开发的一个让玩家轻松创建诸如三维视频游戏、建筑可视化、实时三维动画等类型互动内容的多平台的综合型游戏开发工具,是一个全面整合的专业游戏引擎。

一、场景准备,建立一个简单的场景,一个平板在xz平面,一个红色小圆球代表原点,创建一个半径0.5的小球C位置在(0, 0.5, 0) 

二、创建Shader:

Shader中,将物体的世界坐标作为颜色传给fragment shader, Shader代码如下:

// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

Shader "Unity Shader Book/Chapter5/SimpleShader" {

	SubShader {
		Pass {
			CGPROGRAM

			#pragma vertex vert
			#pragma fragment frag

			//add _Color
			//uniform fixed4 _Color;
			fixed4 _Color;

			struct a2v {
				float4 vertex : POSITION;
			};

			struct v2f {
				float4 pos : SV_POSITION;
				float3 color : COLOR0;	
			};

			v2f vert(a2v v) {
				v2f o;
				o.pos = UnityObjectToClipPos (v.vertex);
				 //这里除法是比例缩放,将世界坐标变换到合适的范围
				o.color = mul(_Object2World, v.vertex).xyz /1.0;   
				return o;
			}

			float4 frag(v2f i) : SV_Target {

//				float dis = length(i.color);
//				return float4(dis, dis, dis, 1.0);	//输出灰度时使用

				float3 f_color = abs(i.color);
				return float4(f_color, 1.0);
			}

			ENDCG
		}
	}
}
创建一个Material,把Shader绑定到Material;再将Material赋给小球C

三、测试

在编辑界面或者运行界面,沿着小球Local坐标系x, y, z轴拖动小球C,可以看到小球颜色变化。

(由于小球都在xz平面以上,y坐标大于零,初始在(0, 0.5, 0)位置时默认偏绿色,所以后面图片里蓝色、红色都和绿色混合了,说明小球表面上的y坐标值大于0)

小球在世界坐标系下:

沿着+-z轴移动时,变蓝色;


沿着+-x轴移动时,变红色;


沿着+-y轴移动时,变绿色;


2018-01-03 14:53:04 q764424567 阅读数 4755
  • Unity 值得看的500+ 技术内容列表

    Unity3D是由Unity Technologies开发的一个让玩家轻松创建诸如三维视频游戏、建筑可视化、实时三维动画等类型互动内容的多平台的综合型游戏开发工具,是一个全面整合的专业游戏引擎。

让物体跟随鼠标移动是很简单的,只需要两行代码:

using UnityEngine;

public class FollowMouse : MonoBehaviour
{
    void Update()
    {
        Vector3 m_MousePos = new Vector3(Input.mousePosition.x, Input.mousePosition.y, 10);
        transform.position = Camera.main.ScreenToWorldPoint(m_MousePos);
    }
}

效果图:
在这里插入图片描述

但是发现问题没有?
我们用了一个固定的参数:
在这里插入图片描述
这个参数的意思是:
摄像机到物体的距离,这个距离如果你没有动摄像机和物体的话(也就是两个都是默认值)就相距10单位:
在这里插入图片描述
在这里插入图片描述

但是!如果两个对象的距离位置变化了呢,这怎么办呢
我们的代码就可以变化一下:

using UnityEngine;

public class FollowMouse : MonoBehaviour
{
    void Update()
    {
        //首先获取到当前物体的屏幕坐标
        Vector3 pos = Camera.main.WorldToScreenPoint(transform.position);
        //让鼠标的屏幕坐标的Z轴等于当前物体的屏幕坐标的Z轴,也就是相隔的距离
        Vector3 m_MousePos = new Vector3(Input.mousePosition.x, Input.mousePosition.y, pos.z);
        //将正确的鼠标屏幕坐标换成世界坐标交给物体
        transform.position = Camera.main.ScreenToWorldPoint(m_MousePos);
    }
}

我们先获取到距离,然后转化为世界坐标就搞定了
效果图:
在这里插入图片描述

2018-07-23 16:42:38 qq_33994566 阅读数 1793
  • Unity 值得看的500+ 技术内容列表

    Unity3D是由Unity Technologies开发的一个让玩家轻松创建诸如三维视频游戏、建筑可视化、实时三维动画等类型互动内容的多平台的综合型游戏开发工具,是一个全面整合的专业游戏引擎。

我在上篇博客写出了如何用代码创建一个我们可以任意控制顶点得圆柱体。本片博客着重记录如何在空间创建类似unity可以控制物体的坐标轴。由于我们要控制圆柱体的长度,所以我们设计的坐标轴是两个方块在圆柱体的两端。效果图如下:

                                                                               

首先我们要绘制两个方块,我们知道空间显示在我们眼前的物体都是通过由多个三角面组成的mesh显示在我们面前的。所以我们首先创建一个属于我们的BOXmesh。代码如下:

public static Mesh CreateBoxMesh(float width, float height, float depth)
        {
            // Clamp dimensions
            width = Mathf.Max(width, 0.0001f);
            height = Mathf.Max(height, 0.0001f);
            depth = Mathf.Max(depth, 0.0001f);

            // Store half dimension values for easy access
            float halfWidth = width * 0.5f;
            float halfHeight = height * 0.5f;
            float halfDepth = depth * 0.5f;

            // Prepare the vertex attribute arrays
            Vector3[] boxVertexPositions = new Vector3[24];
            Vector3[] boxVertexNormals = new Vector3[24];

            // Generate the vertices. Start with the front face
            boxVertexPositions[0] = new Vector3(-halfWidth, -halfHeight, -halfDepth);
            boxVertexPositions[1] = new Vector3(-halfWidth, halfHeight, -halfDepth);
            boxVertexPositions[2] = new Vector3(halfWidth, halfHeight, -halfDepth);
            boxVertexPositions[3] = new Vector3(halfWidth, -halfHeight, -halfDepth);

            boxVertexNormals[0] = -Vector3.forward;
            boxVertexNormals[1] = boxVertexNormals[0];
            boxVertexNormals[2] = boxVertexNormals[0];
            boxVertexNormals[3] = boxVertexNormals[0];

            // Back face
            boxVertexPositions[4] = new Vector3(-halfWidth, -halfHeight, halfDepth);
            boxVertexPositions[5] = new Vector3(halfWidth, -halfHeight, halfDepth);
            boxVertexPositions[6] = new Vector3(halfWidth, halfHeight, halfDepth);
            boxVertexPositions[7] = new Vector3(-halfWidth, halfHeight, halfDepth);

            boxVertexNormals[4] = Vector3.forward;
            boxVertexNormals[5] = boxVertexNormals[4];
            boxVertexNormals[6] = boxVertexNormals[4];
            boxVertexNormals[7] = boxVertexNormals[4];

            // Left face
            boxVertexPositions[8] = new Vector3(-halfWidth, -halfHeight, halfDepth);
            boxVertexPositions[9] = new Vector3(-halfWidth, halfHeight, halfDepth);
            boxVertexPositions[10] = new Vector3(-halfWidth, halfHeight, -halfDepth);
            boxVertexPositions[11] = new Vector3(-halfWidth, -halfHeight, -halfDepth);

            boxVertexNormals[8] = -Vector3.right;
            boxVertexNormals[9] = boxVertexNormals[8];
            boxVertexNormals[10] = boxVertexNormals[8];
            boxVertexNormals[11] = boxVertexNormals[8];

            // Right face
            boxVertexPositions[12] = new Vector3(halfWidth, -halfHeight, -halfDepth);
            boxVertexPositions[13] = new Vector3(halfWidth, halfHeight, -halfDepth);
            boxVertexPositions[14] = new Vector3(halfWidth, halfHeight, halfDepth);
            boxVertexPositions[15] = new Vector3(halfWidth, -halfHeight, halfDepth);

            boxVertexNormals[12] = Vector3.right;
            boxVertexNormals[13] = boxVertexNormals[12];
            boxVertexNormals[14] = boxVertexNormals[12];
            boxVertexNormals[15] = boxVertexNormals[12];

            // Top face
            boxVertexPositions[16] = new Vector3(-halfWidth, halfHeight, -halfDepth);
            boxVertexPositions[17] = new Vector3(-halfWidth, halfHeight, halfDepth);
            boxVertexPositions[18] = new Vector3(halfWidth, halfHeight, halfDepth);
            boxVertexPositions[19] = new Vector3(halfWidth, halfHeight, -halfDepth);

            boxVertexNormals[16] = Vector3.up;
            boxVertexNormals[17] = boxVertexNormals[16];
            boxVertexNormals[18] = boxVertexNormals[16];
            boxVertexNormals[19] = boxVertexNormals[16];

            // Bottom face
            boxVertexPositions[20] = new Vector3(-halfWidth, -halfHeight, -halfDepth);
            boxVertexPositions[21] = new Vector3(halfWidth, -halfHeight, -halfDepth);
            boxVertexPositions[22] = new Vector3(halfWidth, -halfHeight, halfDepth);
            boxVertexPositions[23] = new Vector3(-halfWidth, -halfHeight, halfDepth);

            boxVertexNormals[20] = -Vector3.up;
            boxVertexNormals[21] = boxVertexNormals[20];
            boxVertexNormals[22] = boxVertexNormals[20];
            boxVertexNormals[23] = boxVertexNormals[20];

            // Generate the indices
            int[] vertexIndices = new int[]
            {
                // Front face
                0, 1, 2, 0, 2, 3,

                // Back face
                4, 5, 6, 4, 6, 7,
            
                // Left face
                8, 9, 10, 8, 10, 11,

                // Right face
                12, 13, 14, 12, 14, 15,

                // Top face
                16, 17, 18, 16, 18, 19,

                // Bottom face
                20, 21, 22, 20, 22, 23
            };

            // Create the mesh and return it to the client code
            var boxMesh = new Mesh();
            boxMesh.vertices = boxVertexPositions;
            boxMesh.normals = boxVertexNormals;
            boxMesh.SetIndices(vertexIndices, MeshTopology.Triangles, 0);

            return boxMesh;
        }

创建后的静态函数供我们需要绘制的时候调用。下面我们要设置Boxmesh 的位置,欧拉角以及缩放比。Unity中绘制mesh或者gl线段一般都在OnRenderObject函数中进行。

 protected void OnRenderObject()
    {
        Matrix4x4[] BoxWorldTransforms = GetLengthWorldTransform();
        DrawControlLineLengthAxis(BoxWorldTransforms);
    }

首先我们要设置boxmesh的Transform信息给保存到4*4矩阵中,

 private Matrix4x4[] GetLengthWorldTransform()
    {
        Matrix4x4[] worldTransforms = new Matrix4x4[2];
        Vector3[] localPosition = GetBoxesGizmoLocalPositions(CalculateGizmoScale());
        Quaternion[] localQuaternion = GetBoxesGizmoLocalRotations();

        // Loop through each axis
        for (int i = 0; i < 2; ++i)
        {
            Vector3 worldPosition = _gizmoTransform.position + localPosition[i];
            Quaternion worldRotation = localQuaternion[i];

            // Construct the world transform matrix
            worldTransforms[i] = new Matrix4x4();
            worldTransforms[i].SetTRS(worldPosition, worldRotation, Vector3.Scale(_gizmoTransform.lossyScale, new Vector3(_BoxWidth, _BoxHeight, _BoxDepth)));
        }
        return worldTransforms;
    }

首先来获取boxmesh的位置。我们知道这个自制的坐标轴要在圆柱的两端。而且在上篇博客我们看到我们的圆柱体的左右两侧就是圆柱的forward和-forward,所以获取局部坐标代码如下(lastSelectedGameObject就是我们的圆柱体,tempLeftGizmoPos就是我们在上节所说的leftPos,我们可以在坐标轴显示的初始化函数中获取圆柱体的长度Length,即tempLeftGizmoPos=leftPos=Length/2。gizmoScale就是我们根据摄像机和Boxmesh的距离来自动调节Boxmesh大小的比例系数):

 private Vector3[] GetBoxesGizmoLocalPositions(float gizmoScale)
    {
        return new Vector3[]
        {
                 lastSelectedGameObject.transform.forward*  tempLeftGizmoPos,
                -lastSelectedGameObject.transform.forward * tempRightGizmoPos,
        };
    }

CalculateGizmoScale函数代码如下:

float _gizmoBaseScale =0.77f;
protected float CalculateGizmoScale()
        {
            if (_camera.orthographic)
            {
               
                float scaleConstant = 0.02f;
                return _gizmoBaseScale * _camera.orthographicSize / (_camera.pixelRect.height * scaleConstant);
            }
            else
            {
                const float scaleConstant = 0.045f;
                Vector3 cameraPositionToGizmoOrigin = (this.transform.position - _cameraTransform.position);
                return _gizmoBaseScale * cameraPositionToGizmoOrigin.magnitude / (_camera.pixelRect.height * scaleConstant);
            }
        }
private Quaternion[] GetBoxesGizmoLocalRotations()
    {
        return new Quaternion[]
        {
                Quaternion.identity,
                Quaternion.identity
        };
    }

以上方法我们就可以获取到坐标轴的Transform信息。接下来就将boxmesh的信息给赋值上。

private void DrawControlLineLengthAxis(Matrix4x4[] worldTransforms)
    {
        Material material = MaterialPool.Instance.GizmoSolidComponent;
        material.SetInt("_ZWrite", 1);
        material.SetInt("_ZTest", 0);
        material.SetInt("_IsLit", 1);
        material.SetFloat("_LightIntensity", 1.5f);
        material.SetVector("_LightDir", _cameraTransform.forward);

        Mesh boxMesh = MeshPool.Instance.BoxMesh;
        for (int axisIndex = 3; axisIndex < 5; ++axisIndex)//这里是因为枚举类型里我多添加了两种 X Y Z Left Right
        {
            Color axisColor = axisIndex == (int)selectGizmo ? SelectedAxisColor : _axesColors[2];//当坐标轴被点选后 坐标轴颜色设置高亮的颜色
            //Debug.Log(selectGizmo);
            material.SetColor("_Color", axisColor);
            material.SetInt("_StencilRefValue", _axesStencilRefValues[0]);
            material.SetPass(0);
            Graphics.DrawMeshNow(boxMesh, worldTransforms[axisIndex-3]);
        }
    }

以上就是对自己设计的坐标轴chua创建,当然我们可以仿照unity的XYZ创建属于我们的平移坐标轴。原理类似。

2019-09-19 09:40:08 qq_34735841 阅读数 466
  • Unity 值得看的500+ 技术内容列表

    Unity3D是由Unity Technologies开发的一个让玩家轻松创建诸如三维视频游戏、建筑可视化、实时三维动画等类型互动内容的多平台的综合型游戏开发工具,是一个全面整合的专业游戏引擎。

原本以为只要将鼠标坐标转为世界坐标,然后将转换后的坐标赋给物体就能实现。经多次尝试发现,鼠标转成世界坐标之后缺一Z轴,所以想出的解决方案是先将要跟随的物体的世界坐标转成屏幕坐标,再把该屏幕坐标的Z轴赋给鼠标的Z轴,这样一来,鼠标就具备了Z轴,再将鼠标坐标转为世界坐标,代码如下:

 

 //获取需要移动物体的世界转屏幕坐标
        Vector3 screenPos = Camera.main.WorldToScreenPoint(this.transform.position);
        //获取鼠标位置
        Vector3 mousePos = Input.mousePosition;
        //因为鼠标只有X,Y轴,所以要赋予给鼠标Z轴
        mousePos.z = screenPos.z;
        //把鼠标的屏幕坐标转换成世界坐标
        Vector3 worldPos = Camera.main.ScreenToWorldPoint(mousePos);
        //控制物体移动
        transform.position = worldPos;

 

2017-07-15 13:59:06 u011480667 阅读数 2959
  • Unity 值得看的500+ 技术内容列表

    Unity3D是由Unity Technologies开发的一个让玩家轻松创建诸如三维视频游戏、建筑可视化、实时三维动画等类型互动内容的多平台的综合型游戏开发工具,是一个全面整合的专业游戏引擎。

平面UI跟随场景中的3D物体类似于血条的跟随效果。

经过几种方案的对比发现把3D物体的坐标转化为平面坐标的方案是最行之有效的方法。

下面直接上代码

public class FollwScript : MonoBehaviour
{
public Transform gob3d;//3d物体
public RectTransform imageRec;//2dUI
public Vector3 offset;//两个物体间的偏移量


void Update ()
{
follow();
}
    void follow(){
Vector3 screenPos = Camera.main.WorldToScreenPoint (gob3d.position);
imageRec.position = screenPos+offset;
}
}

没有更多推荐了,返回首页