昨天看到蠻牛上有個練手的文章,要求是實現unity斜邊分屏,就是將屏幕分成兩個三角形,分別顯示兩個照相機顯示的內容,有些端遊也出現過,而且網上也好像沒有這樣的例子,覺得有趣,就寫了一個早上,實現了它,先上效果圖:
上面的例子中,兩個照相機對準的是同一個立方體,觸摸右下角的區域則旋轉立方體,觸摸左上角則移動立方體,達到了簡單的分屏控制效果。
簡單說一下步驟:
1,創建兩個照相機,一個作爲主要相機。另外一個輔助相機是需要取得他的targettexture,;
2,在主相機中重寫OnRenderImage方法;
3,創建一個材質,賦予一個shader,然後將此材質通過上述2中的OnRenderImage方法輸出到最終顯示。shader的作用爲使得主相機的texture和輔助相機的targettexture根據需要顯示在屏幕中的兩個區域;
4,根據屏幕分辨率以及鼠標座標,判斷出鼠標處於哪部分區域,執行旋轉或移動。
下面來詳細實現一下以上步驟:
給Main Camera添加一個腳本,腳本代碼如下:
using UnityEngine;
using System.Collections;
public class Test : MonoBehaviour {
public Camera cam;
public Material mat;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
}
void OnRenderImage(RenderTexture src, RenderTexture dest)
{
if (cam.targetTexture == null)
{
cam.targetTexture = new RenderTexture(cam.pixelWidth, cam.pixelHeight, 0); //根據主相機的寬高創建一個同樣寬高的紋理,記錄輔助相機的圖像
}
mat.SetTexture("_OtherTex", cam.targetTexture);//傳入輔助相機的紋理,shader中用到,具體見下面的shader代碼
Graphics.Blit(src, dest, mat);
}
}
shader代碼如下:
Shader "Custom/Shader" {
Properties {
_MainTex ("Base (RGB) Trans (A)", 2D) = "white" {}//主相機的紋理
_OtherTex ("Other Tex", 2D) = "white" {}<span style="white-space:pre"> </span>//輔助相機的紋理
}
SubShader {
Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"}
LOD 100
Cull Off<span style="white-space:pre"> </span>
Blend Off<span style="white-space:pre"> </span>//關閉混合
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata_t {
float4 vertex : POSITION;
float2 texcoord : TEXCOORD0;
};
struct v2f {
float4 vertex : SV_POSITION;
half2 texcoord : TEXCOORD0;
};
sampler2D _MainTex;
sampler2D _OtherTex;
float4 _MainTex_ST;
v2f vert (appdata_t v)
{
v2f o;
o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
o.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
half2 otherTexcoord = half2(i.texcoord.x, 1 - i.texcoord.y);<span style="white-space:pre"> </span>//本人也不清楚爲什麼外面傳進來的rendertexture的紋理座標的y會相反,所以自己動手用1來減去
fixed4 col = tex2D(_MainTex, i.texcoord)*ceil(i.texcoord.x + i.texcoord.y - 1) + tex2D(_OtherTex, otherTexcoord)*ceil(1 - i.texcoord.x - i.texcoord.y);
return col;
}
ENDCG
}
}
FallBack "Diffuse"
}
上面的shader的核心代碼fixed4 col = tex2D(_MainTex, i.texcoord)*ceil(i.texcoord.x + i.texcoord.y - 1) + tex2D(_OtherTex, otherTexcoord)*ceil(1 - i.texcoord.x - i.texcoord.y);
以上代碼分爲兩部分,其實本質是依靠y = -x + 1這個公式來實現,需要點高中數學知識
經過上面兩部,圖形就已經爲最終效果了,下面來實現分屏控制:
工程裏創建一個空對象ControlObj(上圖中有),給它添加代碼,代碼如下:
using UnityEngine;
using System.Collections;
public class Control : MonoBehaviour {
public Transform obj;
// Use this for initialization
Vector2 mousePos;
float screenWidth = Screen.width;
float screenHeight = Screen.height;
void Start () {
}
// Update is called once per frame
void Update () {
if (Input.GetMouseButtonDown(0))
{
mousePos = Input.mousePosition;
//Debug.Log("按下左鍵" + mousePos);
}
if (Input.GetMouseButton(0))
{
Debug.Log("移動左鍵");
//按照區域判斷是移動還是旋轉
float x = mousePos.x / screenWidth;
float y = mousePos.y / screenHeight;
if (y < x) updateObjRotation();
else updateObjPosition();
}
if (Input.GetMouseButtonUp(0))
{
Debug.Log("鬆開左鍵");
}
}
void updateObjRotation()
{
Debug.Log("更新物體旋轉");
obj.rotation = Quaternion.AngleAxis(1, Vector3.up) * obj.rotation;
}
void updateObjPosition()
{
Debug.Log("更新物體位置");
obj.position = new Vector3(obj.position.x + 0.03f, obj.position.y, obj.position.z);
}
}
核心代碼爲:
<span style="white-space:pre"> </span> //按照區域判斷是移動還是旋轉
float x = mousePos.x / screenWidth;
float y = mousePos.y / screenHeight;
if (y < x) updateObjRotation();
else updateObjPosition();
這是使用了y = x這個公式;
由此大功告成