nearclipcrystal planee和farclipcrystal planee与camera的关系

1137人阅读
建议用ps新建一个rbg为106,106,107的淡黑色图作为这个东东的材质,透明度为40%
Shader &Custom / newMirror & {
Properties {
&&&&_MainTex (&Base (RGB)&, 2D) = &white& {}
&&&&_ReflectionTex (&Reflection&, 2D) = &white& { TexGen ObjectLinear }
// two texture cards: full thing
Subshader {
&&&&Pass {
&&&&&&&&SetTexture[_MainTex] { combine texture }
&&&&&&&&SetTexture[_ReflectionTex] { matrix [_ProjMatrix] combine texture * previous }
// fallback: just main texture
Subshader {
&&&&Pass {
&&&&&&&&SetTexture [_MainTex] { combine texture }
、、、、、、、然后新建一个cs文件& 命名为newMirror.cs
using UnityE
using System.C
// This is in fact just the Water script from Pro Standard Assets,
// just with refraction stuff removed.
[ExecuteInEditMode] // Make mirror live-update even when not in play mode
public class MirrorReflection : MonoBehaviour
&&&&public bool m_DisablePixelLights =
&&&&public int m_TextureSize = 256;
&&&&public float m_ClipPlaneOffset = 0.07f;
&&&&public LayerMask m_ReflectLayers = -1;
&&&&private Hashtable m_ReflectionCameras = new Hashtable(); // Camera -& Camera table
&&&&private RenderTexture m_ReflectionTexture =
&&&&private int m_OldReflectionTextureSize = 0;
&&&&private static bool s_InsideRendering =
&&&&// This is called when it's known that the object will be rendered by some
&&&&// camera. We render reflections and do other updates here.
&&&&// Because the script executes in edit mode, reflections for the scene view
&&&&// camera will just work!
&&&&public void OnWillRenderObject()
&&&&&&&&if( !enabled || !renderer || !renderer.sharedMaterial || !renderer.enabled )
&&&&&&&&&&&&
&&&&&&&&&&
&&&&&&&&Camera cam = Camera.
&&&&&&&&if( !cam )
&&&&&&&&&&&&
&&&&&&&&// Safeguard from recursive reflections.&&&&&&
&&&&&&&&if( s_InsideRendering )
&&&&&&&&&&&&
&&&&&&&&s_InsideRendering =
&&&&&&&&Camera reflectionC
&&&&&&&&CreateMirrorObjects( cam, out reflectionCamera );
&&&&&&&&// find out the reflection plane: position and normal in world space
&&&&&&&&Vector3 pos = transform.
&&&&&&&&Vector3 normal = transform.
&&&&&&&&// Optionally disable pixel lights for reflection
&&&&&&&&int oldPixelLightCount = QualitySettings.pixelLightC
&&&&&&&&if( m_DisablePixelLights )
&&&&&&&&&&&&QualitySettings.pixelLightCount = 0;
&&&&&&&&UpdateCameraModes( cam, reflectionCamera );
&&&&&&&&// Render reflection
&&&&&&&&// Reflect camera around reflection plane
&&&&&&&&float d = -Vector3.Dot (normal, pos) - m_ClipPlaneO
&&&&&&&&Vector4 reflectionPlane = new Vector4 (normal.x, normal.y, normal.z, d);
&&&&&&&&Matrix4x4 reflection = Matrix4x4.
&&&&&&&&CalculateReflectionMatrix (ref reflection, reflectionPlane);
&&&&&&&&Vector3 oldpos = cam.transform.
&&&&&&&&Vector3 newpos = reflection.MultiplyPoint( oldpos );
&&&&&&&&reflectionCamera.worldToCameraMatrix = cam.worldToCameraMatrix *
&&&&&&&&// Setup oblique projection matrix so that near plane is our reflection
&&&&&&&&// plane. This way we clip everything below/above it for free.
&&&&&&&&Vector4 clipPlane = CameraSpacePlane( reflectionCamera, pos, normal, 1.0f );
&&&&&&&&Matrix4x4 projection = cam.projectionM
&&&&&&&&CalculateObliqueMatrix (ref projection, clipPlane);
&&&&&&&&reflectionCamera.projectionMatrix =
&&&&&&&&reflectionCamera.cullingMask = ~(1&&4) & m_ReflectLayers. // never render water layer
&&&&&&&&reflectionCamera.targetTexture = m_ReflectionT
&&&&&&&&GL.SetRevertBackfacing (true);
&&&&&&&&reflectionCamera.transform.position =
&&&&&&&&Vector3 euler = cam.transform.eulerA
&&&&&&&&reflectionCamera.transform.eulerAngles = new Vector3(0, euler.y, euler.z);
&&&&&&&&reflectionCamera.Render();
&&&&&&&&reflectionCamera.transform.position =
&&&&&&&&GL.SetRevertBackfacing (false);
&&&&&&&&Material[] materials = renderer.sharedM
&&&&&&&&foreach( Material mat in materials ) {
&&&&&&&&&&&&if( mat.HasProperty(&_ReflectionTex&) )
&&&&&&&&&&&&&&&&mat.SetTexture( &_ReflectionTex&, m_ReflectionTexture );
&&&&&&&&// Set matrix on the shader that transforms UVs from object space into screen
&&&&&&&&// space. We want to just project reflection texture on screen.
&&&&&&&&Matrix4x4 scaleOffset = Matrix4x4.TRS(
&&&&&&&&&&&&new Vector3(0.5f,0.5f,0.5f), Quaternion.identity, new Vector3(0.5f,0.5f,0.5f) );
&&&&&&&&Vector3 scale = transform.lossyS
&&&&&&&&Matrix4x4 mtx = transform.localToWorldMatrix * Matrix4x4.Scale( new Vector3(1.0f/scale.x, 1.0f/scale.y, 1.0f/scale.z) );
&&&&&&&&mtx = scaleOffset * cam.projectionMatrix * cam.worldToCameraMatrix *
&&&&&&&&foreach( Material mat in materials ) {
&&&&&&&&&&&&mat.SetMatrix( &_ProjMatrix&, mtx );
&&&&&&&&// Restore pixel light count
&&&&&&&&if( m_DisablePixelLights )
&&&&&&&&&&&&QualitySettings.pixelLightCount = oldPixelLightC
&&&&&&&&s_InsideRendering =
&&&&// Cleanup all the objects we possibly have created
&&&&void OnDisable()
&&&&&&&&if( m_ReflectionTexture ) {
&&&&&&&&&&&&DestroyImmediate( m_ReflectionTexture );
&&&&&&&&&&&&m_ReflectionTexture =
&&&&&&&&foreach( DictionaryEntry kvp in m_ReflectionCameras )
&&&&&&&&&&&&DestroyImmediate( ((Camera)kvp.Value).gameObject );
&&&&&&&&m_ReflectionCameras.Clear();
&&&&private void UpdateCameraModes( Camera src, Camera dest )
&&&&&&&&if( dest == null )
&&&&&&&&&&&&
&&&&&&&&// set camera to clear the same way as current camera
&&&&&&&&dest.clearFlags = src.clearF
&&&&&&&&dest.backgroundColor = src.backgroundC&&&&&&
&&&&&&&&if( src.clearFlags == CameraClearFlags.Skybox )
&&&&&&&&&&&&Skybox sky = src.GetComponent(typeof(Skybox)) as S
&&&&&&&&&&&&Skybox mysky = dest.GetComponent(typeof(Skybox)) as S
&&&&&&&&&&&&if( !sky || !sky.material )
&&&&&&&&&&&&{
&&&&&&&&&&&&&&&&mysky.enabled =
&&&&&&&&&&&&}
&&&&&&&&&&&&else
&&&&&&&&&&&&{
&&&&&&&&&&&&&&&&mysky.enabled =
&&&&&&&&&&&&&&&&mysky.material = sky.
&&&&&&&&&&&&}
&&&&&&&&// update other values to match current camera.
&&&&&&&&// even if we are supplying custom camera&projection matrices,
&&&&&&&&// some of values are used elsewhere (e.g. skybox uses far plane)
&&&&&&&&dest.farClipPlane = src.farClipP
&&&&&&&&dest.nearClipPlane = src.nearClipP
&&&&&&&&dest.orthographic = src.
&&&&&&&&dest.fieldOfView = src.fieldOfV
&&&&&&&&dest.aspect = src.
&&&&&&&&dest.orthographicSize = src.orthographicS
&&&&// On-demand create any objects we need
&&&&private void CreateMirrorObjects( Camera currentCamera, out Camera reflectionCamera )
&&&&&&&&reflectionCamera =
&&&&&&&&// Reflection render texture
&&&&&&&&if( !m_ReflectionTexture || m_OldReflectionTextureSize != m_TextureSize )
&&&&&&&&&&&&if( m_ReflectionTexture )
&&&&&&&&&&&&&&&&DestroyImmediate( m_ReflectionTexture );
&&&&&&&&&&&&m_ReflectionTexture = new RenderTexture( m_TextureSize, m_TextureSize, 16 );
&&&&&&&&&&&&m_ReflectionTexture.name = &__MirrorReflection& + GetInstanceID();
&&&&&&&&&&&&m_ReflectionTexture.isPowerOfTwo =
&&&&&&&&&&&&m_ReflectionTexture.hideFlags = HideFlags.DontS
&&&&&&&&&&&&m_OldReflectionTextureSize = m_TextureS
&&&&&&&&// Camera for reflection
&&&&&&&&reflectionCamera = m_ReflectionCameras[currentCamera] as C
&&&&&&&&if( !reflectionCamera ) // catch both not-in-dictionary and in-dictionary-but-deleted-GO
&&&&&&&&&&&&GameObject go = new GameObject( &Mirror Refl Camera id& + GetInstanceID() + & for & + currentCamera.GetInstanceID(), typeof(Camera), typeof(Skybox) );
&&&&&&&&&&&&reflectionCamera = go.
&&&&&&&&&&&&reflectionCamera.enabled =
&&&&&&&&&&&&reflectionCamera.transform.position = transform.
&&&&&&&&&&&&reflectionCamera.transform.rotation = transform.
&&&&&&&&&&&&reflectionCamera.gameObject.AddComponent(&FlareLayer&);
&&&&&&&&&&&&go.hideFlags = HideFlags.HideAndDontS
&&&&&&&&&&&&m_ReflectionCameras[currentCamera] = reflectionC
&&&&&&&&}&&&&&&
&&&&// Extended sign: returns -1, 0 or 1 based on sign of a
&&&&private static float sgn(float a)
&&&&&&&&if (a & 0.0f) return 1.0f;
&&&&&&&&if (a & 0.0f) return -1.0f;
&&&&&&&&return 0.0f;
&&&&// Given position/normal of the plane, calculates plane in camera space.
&&&&private Vector4 CameraSpacePlane (Camera cam, Vector3 pos, Vector3 normal, float sideSign)
&&&&&&&&Vector3 offsetPos = pos + normal * m_ClipPlaneO
&&&&&&&&Matrix4x4 m = cam.worldToCameraM
&&&&&&&&Vector3 cpos = m.MultiplyPoint( offsetPos );
&&&&&&&&Vector3 cnormal = m.MultiplyVector( normal ).normalized * sideS
&&&&&&&&return new Vector4( cnormal.x, cnormal.y, cnormal.z, -Vector3.Dot(cpos,cnormal) );
&&&&// Adjusts the given projection matrix so that near plane is the given clipPlane
&&&&// clipPlane is given in camera space. See article in Game Programming Gems 5.
&&&&private static void CalculateObliqueMatrix (ref Matrix4x4 projection, Vector4 clipPlane)
&&&&&&&&Vector4 q = projection.inverse * new Vector4(
&&&&&&&&&&&&sgn(clipPlane.x),
&&&&&&&&&&&&sgn(clipPlane.y),
&&&&&&&&&&&&1.0f,
&&&&&&&&&&&&1.0f
&&&&&&&&);
&&&&&&&&Vector4 c = clipPlane * (2.0F / (Vector4.Dot (clipPlane, q)));
&&&&&&&&// third row = clip plane - fourth row
&&&&&&&&projection[2] = c.x - projection[3];
&&&&&&&&projection[6] = c.y - projection[7];
&&&&&&&&projection[10] = c.z - projection[11];
&&&&&&&&projection[14] = c.w - projection[15];
&&&&// Calculates reflection matrix around the given plane
&&&&private static void CalculateReflectionMatrix (ref Matrix4x4 reflectionMat, Vector4 plane)
&&&&&&&&reflectionMat.m00 = (1F - 2F*plane[0]*plane[0]);
&&&&&&&&reflectionMat.m01 = (&& - 2F*plane[0]*plane[1]);
&&&&&&&&reflectionMat.m02 = (&& - 2F*plane[0]*plane[2]);
&&&&&&&&reflectionMat.m03 = (&& - 2F*plane[3]*plane[0]);
&&&&&&&&reflectionMat.m10 = (&& - 2F*plane[1]*plane[0]);
&&&&&&&&reflectionMat.m11 = (1F - 2F*plane[1]*plane[1]);
&&&&&&&&reflectionMat.m12 = (&& - 2F*plane[1]*plane[2]);
&&&&&&&&reflectionMat.m13 = (&& - 2F*plane[3]*plane[1]);
&&&&&&&&reflectionMat.m20 = (&& - 2F*plane[2]*plane[0]);
&&&&&&&&reflectionMat.m21 = (&& - 2F*plane[2]*plane[1]);
&&&&&&&&reflectionMat.m22 = (1F - 2F*plane[2]*plane[2]);
&&&&&&&&reflectionMat.m23 = (&& - 2F*plane[3]*plane[2]);
&&&&&&&&reflectionMat.m30 = 0F;
&&&&&&&&reflectionMat.m31 = 0F;
&&&&&&&&reflectionMat.m32 = 0F;
&&&&&&&&reflectionMat.m33 = 1F;
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:32831次
排名:千里之外
原创:30篇
(10)(4)(21)(1)(1)阅读:8519回复:31
一个镜面反射的材质
发布于: 21:28
Shader:Shader &FX/Mirror Reflection& {
Properties {
_MainTex (&Base (RGB)&, 2D) = &white& {}
_ReflectionTex (&Reflection&, 2D) = &white& { TexGen ObjectLinear }
// two texture cards: full thing
Subshader {
SetTexture[_MainTex] { combine texture }
SetTexture[_ReflectionTex] { matrix [_ProjMatrix] combine texture * previous }
// fallback: just main texture
Subshader {
SetTexture [_MainTex] { combine texture }
}C#代码using UnityE
using System.C
// This is in fact just the Water script from Pro Standard Assets,
// just with refraction stuff removed.
[ExecuteInEditMode] // Make mirror live-update even when not in play mode
public class MirrorReflection : MonoBehaviour
public bool m_DisablePixelLights =
public int m_TextureSize = 256;
public float m_ClipPlaneOffset = 0.07f;
public LayerMask m_ReflectLayers = -1;
private Hashtable m_ReflectionCameras = new Hashtable(); // Camera -& Camera table
private RenderTexture m_ReflectionTexture =
private int m_OldReflectionTextureSize = 0;
private static bool s_InsideRendering =
// This is called when it's known that the object will be rendered by some
// camera. We render reflections and do other updates here.
// Because the script executes in edit mode, reflections for the scene view
// camera will just work!
public void OnWillRenderObject()
if( !enabled || !renderer || !renderer.sharedMaterial || !renderer.enabled )
Camera cam = Camera.
if( !cam )
// Safeguard from recursive reflections.
if( s_InsideRendering )
s_InsideRendering =
Camera reflectionC
CreateMirrorObjects( cam, out reflectionCamera );
// find out the reflection plane: position and normal in world space
Vector3 pos = transform.
Vector3 normal = transform.
// Optionally disable pixel lights for reflection
int oldPixelLightCount = QualitySettings.pixelLightC
if( m_DisablePixelLights )
QualitySettings.pixelLightCount = 0;
UpdateCameraModes( cam, reflectionCamera );
// Render reflection
// Reflect camera around reflection plane
float d = -Vector3.Dot (normal, pos) - m_ClipPlaneO
Vector4 reflectionPlane = new Vector4 (normal.x, normal.y, normal.z, d);
Matrix4x4 reflection = Matrix4x4.
CalculateReflectionMatrix (ref reflection, reflectionPlane);
Vector3 oldpos = cam.transform.
Vector3 newpos = reflection.MultiplyPoint( oldpos );
reflectionCamera.worldToCameraMatrix = cam.worldToCameraMatrix *
// Setup oblique projection matrix so that near plane is our reflection
// plane. This way we clip everything below/above it for free.
Vector4 clipPlane = CameraSpacePlane( reflectionCamera, pos, normal, 1.0f );
Matrix4x4 projection = cam.projectionM
CalculateObliqueMatrix (ref projection, clipPlane);
reflectionCamera.projectionMatrix =
reflectionCamera.cullingMask = ~(1&&4) ; m_ReflectLayers. // never render water layer
reflectionCamera.targetTexture = m_ReflectionT
GL.SetRevertBackfacing (true);
reflectionCamera.transform.position =
Vector3 euler = cam.transform.eulerA
reflectionCamera.transform.eulerAngles = new Vector3(0, euler.y, euler.z);
reflectionCamera.Render();
reflectionCamera.transform.position =
GL.SetRevertBackfacing (false);
Material[] materials = renderer.sharedM
foreach( Material mat in materials ) {
if( mat.HasProperty(&_ReflectionTex&) )
mat.SetTexture( &_ReflectionTex&, m_ReflectionTexture );
// Set matrix on the shader that transforms UVs from object space into screen
// space. We want to just project reflection texture on screen.
Matrix4x4 scaleOffset = Matrix4x4.TRS(
new Vector3(0.5f,0.5f,0.5f), Quaternion.identity, new Vector3(0.5f,0.5f,0.5f) );
Vector3 scale = transform.lossyS
Matrix4x4 mtx = transform.localToWorldMatrix * Matrix4x4.Scale( new Vector3(1.0f/scale.x, 1.0f/scale.y, 1.0f/scale.z) );
mtx = scaleOffset * cam.projectionMatrix * cam.worldToCameraMatrix *
foreach( Material mat in materials ) {
mat.SetMatrix( &_ProjMatrix&, mtx );
// Restore pixel light count
if( m_DisablePixelLights )
QualitySettings.pixelLightCount = oldPixelLightC
s_InsideRendering =
// Cleanup all the objects we possibly have created
void OnDisable()
if( m_ReflectionTexture ) {
DestroyImmediate( m_ReflectionTexture );
m_ReflectionTexture =
foreach( DictionaryEntry kvp in m_ReflectionCameras )
DestroyImmediate( ((Camera)kvp.Value).gameObject );
m_ReflectionCameras.Clear();
private void UpdateCameraModes( Camera src, Camera dest )
if( dest == null )
// set camera to clear the same way as current camera
dest.clearFlags = src.clearF
dest.backgroundColor = src.backgroundC
if( src.clearFlags == CameraClearFlags.Skybox )
Skybox sky = src.GetComponent(typeof(Skybox)) as S
Skybox mysky = dest.GetComponent(typeof(Skybox)) as S
if( !sky || !sky.material )
mysky.enabled =
mysky.enabled =
mysky.material = sky.
// update other values to match current camera.
// even if we are supprojection matrices,
// some of values are used elsewhere (e.g. skybox uses far plane)
dest.farClipPlane = src.farClipP
dest.nearClipPlane = src.nearClipP
dest.orthographic = src.
dest.fieldOfView = src.fieldOfV
dest.aspect = src.
dest.orthographicSize = src.orthographicS
// On-demand create any objects we need
private void CreateMirrorObjects( Camera currentCamera, out Camera reflectionCamera )
reflectionCamera =
// Reflection render texture
if( !m_ReflectionTexture || m_OldReflectionTextureSize != m_TextureSize )
if( m_ReflectionTexture )
DestroyImmediate( m_ReflectionTexture );
m_ReflectionTexture = new RenderTexture( m_TextureSize, m_TextureSize, 16 );
m_ReflectionTexture.name = &__MirrorReflection& + GetInstanceID();
m_ReflectionTexture.isPowerOfTwo =
m_ReflectionTexture.hideFlags = HideFlags.DontS
m_OldReflectionTextureSize = m_TextureS
// Camera for reflection
reflectionCamera = m_ReflectionCameras[currentCamera] as C
if( !reflectionCamera ) // catch both not-in-dictionary and in-dictionary-but-deleted-GO
GameObject go = new GameObject( &Mirror Refl Camera id& + GetInstanceID() + & for & + currentCamera.GetInstanceID(), typeof(Camera), typeof(Skybox) );
reflectionCamera = go.
reflectionCamera.enabled =
reflectionCamera.transform.position = transform.
reflectionCamera.transform.rotation = transform.
reflectionCamera.gameObject.AddComponent(&FlareLayer&);
go.hideFlags = HideFlags.HideAndDontS
m_ReflectionCameras[currentCamera] = reflectionC
// Extended sign: returns -1, 0 or 1 based on sign of a
private static float sgn(float a)
if (a & 0.0f) return 1.0f;
if (a & 0.0f) return -1.0f;
return 0.0f;
// Given position/normal of the plane, calculates plane in camera space.
private Vector4 CameraSpacePlane (Camera cam, Vector3 pos, Vector3 normal, float sideSign)
Vector3 offsetPos = pos + normal * m_ClipPlaneO
Matrix4x4 m = cam.worldToCameraM
Vector3 cpos = m.MultiplyPoint( offsetPos );
Vector3 cnormal = m.MultiplyVector( normal ).normalized * sideS
return new Vector4( cnormal.x, cnormal.y, cnormal.z, -Vector3.Dot(cpos,cnormal) );
// Adjusts the given projection matrix so that near plane is the given clipPlane
// clipPlane is given in camera space. See article in Game Programming Gems 5.
private static void CalculateObliqueMatrix (ref Matrix4x4 projection, Vector4 clipPlane)
Vector4 q = projection.inverse * new Vector4(
sgn(clipPlane.x),
sgn(clipPlane.y),
Vector4 c = clipPlane * (2.0F / (Vector4.Dot (clipPlane, q)));
// third row = clip plane - fourth row
projection[2] = c.x - projection[3];
projection[6] = c.y - projection[7];
projection[10] = c.z - projection[11];
projection[14] = c.w - projection[15];
// Calculates reflection matrix around the given plane
private static void CalculateReflectionMatrix (ref Matrix4x4 reflectionMat, Vector4 plane)
reflectionMat.m00 = (1F - 2F*plane[0]*plane[0]);
reflectionMat.m01 = (
- 2F*plane[0]*plane[1]);
reflectionMat.m02 = (
- 2F*plane[0]*plane[2]);
reflectionMat.m03 = (
- 2F*plane[3]*plane[0]);
reflectionMat.m10 = (
- 2F*plane[1]*plane[0]);
reflectionMat.m11 = (1F - 2F*plane[1]*plane[1]);
reflectionMat.m12 = (
- 2F*plane[1]*plane[2]);
reflectionMat.m13 = (
- 2F*plane[3]*plane[1]);
reflectionMat.m20 = (
- 2F*plane[2]*plane[0]);
reflectionMat.m21 = (
- 2F*plane[2]*plane[1]);
reflectionMat.m22 = (1F - 2F*plane[2]*plane[2]);
reflectionMat.m23 = (
- 2F*plane[3]*plane[2]);
reflectionMat.m30 = 0F;
reflectionMat.m31 = 0F;
reflectionMat.m32 = 0F;
reflectionMat.m33 = 1F;
}材质中选择新建的Shader,与C#同时应用到目标物体。
最新喜欢:
新浪微博:/zhiweifire
个人主页:/zhiweifire/
行有不得者反求诸己
鲜花1455朵
发布于: 21:53
相当不错!!!!!!!!!!
鲜花1046朵
发布于: 07:04
发布于: 10:10
写Shader好难啊 不过还是学习了!
发布于: 20:15
感觉难,不过想学
发布于: 20:37
谢谢了,套用一下
鲜花6503朵
发布于: 00:53
做事像山 做人像水
发布于: 09:34
感谢,总算明白反射贴图是咋来的了
发布于: 14:21
感谢楼主分享
发布于: 16:35
地形包 包括多种树木、花草
您需要登录后才可以回帖,&或者&
Powered byunity 编辑器跟插件制作(四.2) - 移动开发
&&&unity 编辑器跟插件制作(四.2) unity 编辑器跟插件制作(四.2) ,网友分享于:&&&浏览:6次
unity 编辑器和插件制作(四.2)上次 我们讲述的是编辑器制作,怎么把图片加载到场景中,今天 我们就来讲述下,怎么 制作UIButton以及UIimage的互换。
废话不多说。进入正题。
首先我们要了解 unity的机制,button属性必须有的属性等。
首先 我们先说下 unity的机制:
unity中检测点击事件,使用NGUI的可能知道,NGUI使用的就是SendMessage的方式来进行事件的传递。没错,这也是 unity最为简便的方式,
(要注意一个问题哦,这个方式 如果 你要使用 大于 万次循环的话 会有延迟的哦,一般也不会同时发送万条事件的)。
我们知道了 事件的传送的方式,那么我们就开始制作这个规则,首先 要使用SendMessage的话我们要拿到gameobject的对象才能使用。
所以我们要想办法拿到点击的那个物体。怎么坐那,原理其实很简单,就是射线。我们都知道,unity的射线是用来探测使用的 正好,我们所有可以看到的物体都是存在camera下面,那么我们就可以使用,从camera上发射射线,来达到检测物体的作用,物体要有碰撞体哦。
先贴部分代码等这个章节完了我会贴完整的代码
Ray cameraR
Vector3 touchPos,pressOffS
public static GameObject touchObj =
public static VKCamera shareVkC
void Update () {
#if UNITY_EDITOR
if(Input.GetMouseButtonDown(0)){
onPressDown(Input.mousePosition);
}else if(Input.GetMouseButtonUp(0)){
onPressUp(Input.mousePosition);
}else if(Input.GetMouseButton(0)){
onDrag(Input.mousePosition);
#if UNITY_IPHONE || UNITY_ANDROID
if(Input.touchCount==1){
touch = Input.GetTouch (0);
switch(touch.phase){
case TouchPhase.Began:
onPressDown(touch.position);
case TouchPhase.Moved:
onPressUp(touch.position);
case TouchPhase.Ended:
case TouchPhase.Canceled:
onDrag(touch.position);
if(Input.GetMouseButtonDown(0)){
onPressDown(Input.mousePosition);
}else if(Input.GetMouseButtonUp(0)){
onPressUp(Input.mousePosition);
}else if(Input.GetMouseButton(0)){
onDrag(Input.mousePosition);
public void onPressDown(Vector2 vec){
touchPos =
for(int i=0 ; i&Camera.allCameras.Li++){
cameraRay = Camera.allCameras[i].ScreenPointToRay(touchPos);
if(Physics.Raycast(cameraRay,out hit,9999,Camera.allCameras[i].cullingMask) && touchObj == null){
touchObj = hit.transform.gameO
if(touchObj!=null && touchObj.GetComponent&VKButton&()){
touchPos = Camera.allCameras[i].ScreenToWorldPoint(touchPos);
pressOffSet =touchObj.transform.position-touchP
VKButton button = touchObj.GetComponent&VKButton&();
if(!iSNull(button.pressEventName) && button.eventObj!=null)
button.eventObj.SendMessage(button.pressEventName,button);
if(button.pressButtonTex!=null){
button.renderer.sharedMaterial.mainTexture = button.pressButtonT
if(button.isDrag && !iSNull(button.dragStartEventName)){
button.eventObj.SendMessage(button.dragStartEventName,vec);
if(button.isAni){
button.SendMessage(&onPressAni&);
public void onPressUp(Vector2 vec){
if(touchObj!=null){
VKButton button = touchObj.GetComponent&VKButton&();
if(button!=null){
if(button.buttonTex!=null){
touchObj.renderer.sharedMaterial.mainTexture =
touchObj.GetComponent&VKButton&().buttonT
if(!iSNull(button.clickEventName) && button.eventObj!=null){
button.eventObj.SendMessage(button.clickEventName,button);
if(button.isDrag && !iSNull(button.dragEndEventName)){
button.SendMessage(button.dragEndEventName,vec);
if(button.isAni){
button.SendMessage(&onClickAni&);
touchObj =
public void onDrag(Vector2 vec){
if(touchObj!=null){
VKButton button = touchObj.GetComponent&VKButton&();
if(button!=null && button.isDrag){
for(int i= 0;i&Camera.allCameras.Li++){
Vector2 worldVec =
Camera.allCameras[i].ScreenToWorldPoint(vec);
touchObj.transform.position = new Vector3(worldVec.x+pressOffSet.x,worldVec.y+pressOffSet.y,touchObj.transform.position.z);
if(!iSNull(button.dragEventName))
button.eventObj.SendMessage(button.dragEventName,worldVec);
bool iSNull(string eventName){
bool buttonIsNull =
if(eventName== null || eventName.Equals(&null&)){
buttonIsNull
return buttonIsN
这些是camera的部分,还有一点这个 我们没有贴我的适配方案 摄像机的适配方案,这里统配是的设计方案,因为这里我估计还要改下,发现这个摄像机适配方案,超出了unity的物理引擎的范围。不建议,不过可以参考。
public void initVKCamere(){
gameObject.name = &VKCamere&;
this.camera.orthographic =
this.camera.backgroundColor = Color.
this.camera.nearClipPlane = 0;
this.camera.farClipPlane = 9999;
this.camera.orthographic =
this.camera.orthographicSize = getCameraSize ();
this.transform.position = new Vector3(0,0,-1000);
this.transform.rotation = Quaternion.Euler(Vector3.zero);
this.transform.localScale = Vector3.
Application.targetFrameRate=60;
if(GetComponent&AudioListener&()){
//DestroyImmediate(GetComponent&AudioListener&());
int getCameraSize(){
int size = 384;
bool isLandscape=(Camera.main.pixelWidth&Camera.main.pixelHeight);
float rad = Camera.main.pixelWidth/Camera.main.pixelH
bool isIPad= (Mathf.Abs(rad-1.3333f)&0.001f) || (Mathf.Abs(rad-0.75f)&0.001f);
if(isIPad){
if(isLandscape){
if(isLandscape){
//iPhone 5
if(Camera.main.pixelHeight/Camera.main.pixelWidth&1.6){
camera的编辑器类
using UnityE
using UnityE
using System.C
[CustomEditor(typeof(VKCamera))]
public class VKCameraEditor : Editor {
public override void OnInspectorGUI (){
base.OnInspectorGUI();
VKCamera vkCamere = (VKCamera)
if(GUILayout.Button(&ReSetCamera&)){
vkCamere.initVKCamere();
EditorUtility.SetDirty(vkCamere);
EditorUtility.UnloadUnusedAssets();
好下面我们来讲述下,button的一些东西,其实就很简单了。只是在编辑器方面可能会有些麻烦。
说白了 就是button就来处理 摄像机发来的东西。虽然很简单的一句话,但我们写得东西还是有很多的。
依然,button还是继承前面的view
using UnityE
using System.C
using Holoville.HOT
//[RequireComponent(typeof(BoxCollider))]
public class VKButton : VKView {
[HideInInspector] public Material buttonDefultM
[HideInInspector] public Mesh buttonDefultM
[HideInInspector] public Texture buttonTex,pressButtonT
[HideInInspector] public string pressEventName =
[HideInInspector] public string clickEventName =
[HideInInspector] public string dragStartEventName =
[HideInInspector] public string dragEventName =
[HideInInspector] public string dragEndEventName =
[HideInInspector] public GameObject eventObj =
[HideInInspector] public string eventScript =
[HideInInspector] public bool isDrag =
[HideInInspector] public float scale = 1;
[HideInInspector] public string info=
[HideInInspector] public string[] animatorType = new string[]{&null&,&bigger&,&smaller&,&moveLeft&,&moveRight&};
[HideInInspector] public int currentAnimator = 0;
[HideInInspector] public bool isAni =
void Start () {
buttonDefultMat = new Material(Shader.Find(&VK/VKButtonShader&));
gameObject.GetComponent&MeshRenderer& ().material = buttonDefultM
buttonDefultMesh = new Mesh ();
gameObject.GetComponent&MeshFilter& ().mesh = buttonDefultM
if(GetComponent&BoxCollider&()== null)
gameObject.AddComponent&BoxCollider&();
updateButton();
public float setScale{
public void updateButton(){
if(buttonTex!=null){
if(buttonDefultMat!=null)
buttonDefultMat.mainTexture = buttonT
if(buttonDefultMesh!=null)
buttonDefultMesh.vertices = InitBase.initVertice(buttonTex.width *scale,buttonTex.height*scale,ancPointx,ancPointy);
if(this!=null&&gameObject.GetComponent&BoxCollider&()!=null){
gameObject.GetComponent&BoxCollider&().size = new Vector3(buttonTex.width*scale,buttonTex.height*scale,0);
if(buttonDefultMat!=null)
buttonDefultMat.mainTexture =
if(buttonDefultMesh!=null)
buttonDefultMesh.vertices = InitBase.initVertice(width*scale,height*scale,ancPointx,ancPointy);
gameObject.GetComponent&BoxCollider&().size = new Vector3(width,height,0);
if(buttonDefultMesh!= null){
buttonDefultMesh.triangles = InitBase.initTri ();
buttonDefultMesh.normals = InitBase.initNormal();
buttonDefultMesh.uv = InitBase.initUV();
Vector3 pressScale= Vector3.
Vector3 pressPos = Vector3.
Tweener tw =
void onPressAni(){
if(tw!=null && !tw.isComplete){
pressScale = transform.localS
pressPos = transform.
switch(currentAnimator){
tw = VKAnimator.scaleBy(gameObject,0.3f,Vector3.one*0.2f,VkAniDuration.AnimationCurve,null);
tw = VKAnimator.scaleBy(gameObject,0.3f,Vector3.one*-0.2f,VkAniDuration.AnimationCurve,null);
tw = VKAnimator.moveBy(gameObject,0.3f,new Vector3(-10f,0,0),false,VkAniDuration.AnimationCurve,null);
tw = VKAnimator.moveBy(gameObject,0.3f,new Vector3(10f,0,0),false,VkAniDuration.AnimationCurve,null);
void onClickAni(){
if(currentAnimator == 1 || currentAnimator==2){
VKAnimator.scaleTo(gameObject,0.3f,pressScale,VkAniDuration.AnimationCurve,null);
} else if(currentAnimator == 3 || currentAnimator==4){
VKAnimator.moveTo(gameObject,0.3f,pressPos,false,VkAniDuration.AnimationCurve,null);
public void switchImageView(){
VKImageView imgView = gameObject.AddComponent&VKImageView& ();
imgView.imgViewTex = buttonT
imgView.highLightedTex = pressButtonT
imgView.ancPointx = ancP
imgView.ancPointy = ancP
imgView.scale =
imgView.updateImageView ();
if(GetComponent&BoxCollider&()){
DestroyImmediate(GetComponent&BoxCollider&());
DestroyImmediate (GetComponent&VKButton&());
这里有个 动画效果 我是自己使用的hotween整合的一些东西,如果你想用自己的可以自己去做。hotween插件 我就不用公布了,可以去官网进行下载,各大论坛也有下载资源。
using UnityE
using System.C
using Holoville.HOT
public enum VkAniDuration{
AnimationCurve = EaseType.AnimationCurve,
EaseInBack=EaseType.EaseInBack,
EaseInBounce=EaseType.EaseInBounce,
EaseInCirc=EaseType.EaseInCirc,
EaseInCubic=EaseType.EaseInCubic,
EaseInElastic=EaseType.EaseInElastic,
EaseInExpo=EaseType.EaseInExpo,
EaseInOutBack=EaseType.EaseInOutBack,
EaseInOutBounce=EaseType.EaseInOutBounce,
EaseInOutCirc=EaseType.EaseInOutCirc,
EaseInOutCubic=EaseType.EaseInOutCubic,
EaseInOutElastic=EaseType.EaseInOutElastic,
EaseInOutExpo=EaseType.EaseInOutExpo,
EaseInOutQuad=EaseType.EaseInOutQuad,
EaseInOutQuart=EaseType.EaseInOutQuart,
EaseInOutQuint=EaseType.EaseInOutQuint,
EaseInOutSine=EaseType.EaseInOutSine,
EaseInQuad=EaseType.EaseInQuad,
EaseInQuart=EaseType.EaseInQuart,
EaseInQuint=EaseType.EaseInQuint,
EaseInSine=EaseType.EaseInSine,
EaseOutBack=EaseType.EaseOutBack,
EaseOutBounce=EaseType.EaseOutBounce,
EaseOutCirc=EaseType.EaseOutCirc,
EaseOutCubic=EaseType.EaseOutCubic,
EaseOutElastic=EaseType.EaseOutElastic,
EaseOutExpo=EaseType.EaseOutExpo,
EaseOutQuad=EaseType.EaseOutQuad,
EaseOutQuart=EaseType.EaseOutQuart,
EaseOutQuint=EaseType.EaseOutQuint,
EaseOutSine=EaseType.EaseOutSine,
Linear=EaseType.Linear
public class VKAnimator {
// public static Tweener moveTo(GameObject obj,float time,Vector3 target,bool isLocal,VkAniDuration vkDurType = VkAniDuration.AnimationCurve){
Tweener tw =
if(isLocal)
tw = startVkAnimote(obj,time,&localPosition&,target,vkDurType,null);
tw = startVkAnimote(obj,time,&position&,target,vkDurType,null);
public static Tweener moveTo(GameObject obj,float time,Vector3 target,bool isLocal,VkAniDuration vkDurType = VkAniDuration.AnimationCurve,VKAniComplete completeObj = null){
Tweener tw =
if(isLocal)
tw =startVkAnimote(obj,time,&localPosition&,target,vkDurType,completeObj);
tw = startVkAnimote(obj,time,&position&,target,vkDurType,completeObj);
public static Tweener moveBy(GameObject obj,float time,Vector3 offset,bool isLocal,VkAniDuration vkDurType = VkAniDuration.AnimationCurve,VKAniComplete completeObj = null){
Tweener tw =
if(isLocal){
Vector3 tLocalPos = obj.transform.localPosition +
tw = startVkAnimote(obj,time,&localPosition&,tLocalPos,vkDurType,completeObj);
Vector3 tPos = obj.transform.position +
tw = startVkAnimote(obj,time,&position&,tPos,vkDurType,completeObj);
public static Tweener scaleTo(GameObject obj,float time,Vector3 scale,VkAniDuration vkDurType = VkAniDuration.AnimationCurve,VKAniComplete completeObj = null){
Tweener tw =
tw = startVkAnimote(obj,time,&localScale&,scale,vkDurType,completeObj);
public static Tweener scaleBy(GameObject obj,float time,Vector3 offsetScale,VkAniDuration vkDurType = VkAniDuration.AnimationCurve,VKAniComplete completeObj = null){
Tweener tw =
Vector3 targetScale = obj.transform.localScale+offsetS
tw = startVkAnimote(obj,time,&localScale&,targetScale,vkDurType,completeObj);
public static Tweener routeTo(GameObject obj,float time,Vector3 routeEulerTarget,VkAniDuration vkDurType = VkAniDuration.AnimationCurve,VKAniComplete completeObj = null){
Tweener tw =
tw = startVkAnimote(obj,time,&localEulerAngles&,routeEulerTarget,vkDurType,completeObj);
public static Tweener routeBy(GameObject obj,float time,Vector3 routeEulerOffset,VkAniDuration vkDurType = VkAniDuration.AnimationCurve,VKAniComplete completeObj = null){
Tweener tw =
Vector3 target = obj.transform.localEulerAngles+ routeEulerO
tw = startVkAnimote(obj,time,&localEulerAngles&,target,vkDurType,completeObj);
//localEulerAngles
private static Tweener startVkAnimote(GameObject obj,float time,string key,object target,VkAniDuration vkDurType = VkAniDuration.AnimationCurve,VKAniComplete completeObj = null){
Tweener tw =
TweenParms twp = new TweenParms();
twp.Prop(key,target);
twp.Ease((EaseType)vkDurType);
if(completeObj!=null){
twp.OnComplete(completeObj.sendTargetObj,completeObj.methodName,completeObj.sendobj,SendMessageOptions.DontRequireReceiver);
HOTween.To(obj.transform,time,twp);
using UnityE
using System.C
public class VKAniComplete{
public GameObject sendTargetObj =
public string methodName =
public object sendobj =
public VKAniComplete(GameObject sendTargetObj,string methodName,object sendobj){
this.sendTargetObj = sendTargetO
this.methodName = methodN
this.sendobj =
下面就是button的编辑器方面了。ok,这里可能有点麻烦。不过还是可以解决的。
首先我们要获取脚本里面的方法怎么获取那。根据c#的MSDN的描述我们可以看到。就是以下方法,这就是 为什么 NGUI 只能找到public属性的方法。
using UnityE
using System.C
using System.R
public class GetPublic : MonoBehaviour {
static public
MethodInfo[] GetObjectMethods(string selectedObjClass){
if(selectedObjClass==null)
MethodInfo[] methodInfos=
if(System.Type.GetType(selectedObjClass)==null){
return methodI
methodInfos =
System.Type.GetType(selectedObjClass).GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
return methodI
这里就是button编辑器的一些属性的传递,和界面的修改哈。
using UnityE
using System.C
using UnityE
using System.R
[CustomEditor(typeof(VKButton))]
public class VKButtonEditor : Editor {
public override void OnInspectorGUI ()
int pressEventNum= 0;
int selectScriptNum = 0;
int clickEventNum = 0;
int dragStartEveNum = 0;
int dragEveNum = 0;
int dragEndEveNum = 0;
VKButton button = (VKButton)
button.buttonTex = EditorGUILayout.ObjectField (&Texture&,button.buttonTex,typeof(Texture),true)as T
button.pressButtonTex = EditorGUILayout.ObjectField (&PressButtonTex&,button.pressButtonTex,typeof(Texture),true)as T
button.eventObj = EditorGUILayout.ObjectField(&eventObj&,button.eventObj,typeof(GameObject),true) as GameO
= EditorGUILayout.TextField(&info&,);
button.ancPointx = EditorGUILayout.Slider(&AnchorX&,button.ancPointx,0.0f,1.0f);
button.ancPointy = EditorGUILayout.Slider(&AnchorY&,button.ancPointy,0.0f,1.0f);
if(button.buttonTex == null){
button.width=EditorGUILayout.IntField(&Width&,button.width);
button.height=EditorGUILayout.IntField(&Height&,button.height);
GUILayout.BeginHorizontal();
if(GUILayout.Button(&2X&)){
button.setScale = 0.5f;
if(GUILayout.Button(&1X&)){
button.setScale = 1f;
if(GUILayout.Button(&1.5X&)){
button.setScale = 0.75f;
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
if(GUILayout.Button(&ChangeName&)){
if(button.buttonTex!=null){
button.name = button.buttonTex.
if(GUILayout.Button(&Switch ImageView&)){
button.switchImageView();
GUILayout.EndHorizontal();
if(button.eventObj!=null){
MonoBehaviour[] monoScriptArry =new MonoBehaviour[button.eventObj.GetComponents&MonoBehaviour&().Length+1];// button.eventObj.GetComponents&MonoBehaviour&();
for(int i=0;i&monoScriptArry.Li++){
if(i&monoScriptArry.Length-1)
monoScriptArry [i] = button.eventObj.GetComponents&MonoBehaviour&()[i];
if(i == monoScriptArry.Length-1){
monoScriptArry [i] =
if(monoScriptArry !=null&& monoScriptArry.Length&0){
string [] scriptName = new string[monoScriptArry.Length];
for(int i=0;i&scriptName.Li++){
if(monoScriptArry[i]!=null){
scriptName[i] = monoScriptArry[i].GetType().ToString();
if(scriptName[i].Equals(&VKCamera&)){
scriptName[i] = &null&;
scriptName[i] = &null&;
if(scriptName[i].Equals(button.eventScript)){
selectScriptNum =
selectScriptNum = EditorGUILayout.Popup(&EventScript&,selectScriptNum,scriptName);
button.eventScript = scriptName[selectScriptNum];
MethodInfo[] publicMethodA
if(button.eventScript == null || button.eventScript.Equals(&null&)){
publicMethodArry = new MethodInfo[1];
publicMethodArry = new MethodInfo[GetPublic.GetObjectMethods(button.eventScript).Length+1];
for(int i = 0;i&publicMethodArry.Li++){
if(i&publicMethodArry.Length-1){
publicMethodArry[i] =GetPublic.GetObjectMethods(button.eventScript)[i];
publicMethodArry[i] =
if(publicMethodArry!=null && publicMethodArry.Length&0){
string[] methodArry = new string[publicMethodArry.Length];
for(int i=0;i&methodArry.Li++){
if(publicMethodArry[i]!=null){
methodArry[i] = publicMethodArry[i].N
methodArry[i] =&null&;
if(button.pressEventName !=null && button.pressEventName.Equals(methodArry[i])){
pressEventNum =
if(button.clickEventName != null && button.clickEventName.Equals(methodArry[i])){
clickEventNum =
if(button.isDrag){
if(button.dragStartEventName != null && button.dragStartEventName.Equals(methodArry[i])){
dragStartEveNum =
if(button.dragEventName != null && button.dragEventName.Equals(methodArry[i])){
dragEveNum =
if(button.dragEndEventName != null && button.dragEndEventName.Equals(methodArry[i])){
dragEndEveNum =
pressEventNum = EditorGUILayout.Popup(&PressEvent&,pressEventNum,methodArry);
clickEventNum = EditorGUILayout.Popup(&ClickEvent&,clickEventNum,methodArry);
button.pressEventName = methodArry[pressEventNum];
button.clickEventName = methodArry[clickEventNum];
button.isAni = EditorGUILayout.Toggle (&ISAimator&,button.isAni);
if(button.isAni){
button.currentAnimator = EditorGUILayout.Popup(&ButtonAnimator&,button.currentAnimator,button.animatorType);
button.isDrag =
EditorGUILayout.Toggle (&ISDrag&,button.isDrag);
if(button.isDrag){
EditorGUILayout.LabelField(&---------------------------------------------&);
dragStartEveNum = EditorGUILayout.Popup(&DragStartEvent&,dragStartEveNum,methodArry);
dragEveNum = EditorGUILayout.Popup(&DragEvent&,dragEveNum,methodArry);
dragEndEveNum = EditorGUILayout.Popup(&DragEndEvent&,dragEndEveNum,methodArry);
button.dragStartEventName = methodArry[dragStartEveNum];
button.dragEventName = methodArry[dragEveNum];
button.dragEndEventName
=methodArry[dragEndEveNum];
pressEventNum = EditorGUILayout.Popup(&PressEvent&,pressEventNum,new string[]{&null&});
clickEventNum = EditorGUILayout.Popup(&ClickEvent&,clickEventNum,new string[]{&null&});
button.isAni =
button.isDrag =
button.updateButton ();
if(button!=null){
EditorUtility.SetDirty(button);
EditorUtility.UnloadUnusedAssets();
我这里扩展了一些功能,像移动啊,什么的。。其实还可以加一些功能的 ,这里只是学习。有兴趣的可以自己加些东西。
相关解决方案
各类解决方案WEB开发数据库移动开发企业软件/开发硬件/嵌入开发JAVA应用服务器软件工程/管理/测试.NETLinux/Unix多媒体开发语言/框架专题开发/技术/项目综合高性能开发硬件设备Windows培训认证 Copyright &

我要回帖

更多关于 backplane 的文章

 

随机推荐