Initial Commit
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b9a6847cfb4aa714abf08e7d17effd2a
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,84 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!21 &2100000
|
||||
Material:
|
||||
serializedVersion: 6
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_Name: ColumnGlow
|
||||
m_Shader: {fileID: 4800000, guid: 25bc671e448181c4fab3e6f52fb9d4bd, type: 3}
|
||||
m_ShaderKeywords:
|
||||
m_LightmapFlags: 5
|
||||
m_EnableInstancingVariants: 0
|
||||
m_DoubleSidedGI: 0
|
||||
m_CustomRenderQueue: 3000
|
||||
stringTagMap: {}
|
||||
disabledShaderPasses: []
|
||||
m_SavedProperties:
|
||||
serializedVersion: 3
|
||||
m_TexEnvs:
|
||||
- _BumpMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailAlbedoMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailMask:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailNormalMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _EmissionMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _MainTex:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _MetallicGlossMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _OcclusionMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _ParallaxMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_Floats:
|
||||
- _BumpScale: 1
|
||||
- _Cutoff: 0.5
|
||||
- _DetailNormalMapScale: 1
|
||||
- _DstBlend: 0
|
||||
- _EdgePosition: 1
|
||||
- _FadeEnd: -1
|
||||
- _FadeStart: 1
|
||||
- _FrontFactor: 0
|
||||
- _Glossiness: 0.5
|
||||
- _GlowEnd: 0.07
|
||||
- _GlowEndEnd: 0
|
||||
- _GlowStart: 0.33
|
||||
- _GlowStartEnd: 0.3
|
||||
- _Intensity: 0.5
|
||||
- _InvFade: 1
|
||||
- _Metallic: 0
|
||||
- _Mode: 0
|
||||
- _OcclusionStrength: 1
|
||||
- _Parallax: 0.02
|
||||
- _SrcBlend: 1
|
||||
- _Thickness: 0.5
|
||||
- _UVSec: 0
|
||||
- _ZWrite: 1
|
||||
m_Colors:
|
||||
- _Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
|
||||
- _TintColor: {r: 0.006109435, g: 0.8308824, b: 0.7284968, a: 0.5}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5e53c7a8c2e563c4c90a8fa620eebc2c
|
||||
timeCreated: 1446211093
|
||||
licenseType: Store
|
||||
NativeFormatImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,86 @@
|
||||
/************************************************************************************
|
||||
|
||||
Copyright (c) Facebook Technologies, LLC and its affiliates. All rights reserved.
|
||||
|
||||
See SampleFramework license.txt for license terms. Unless required by applicable law
|
||||
or agreed to in writing, the sample code is provided "AS IS" WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied. See the license for specific
|
||||
language governing permissions and limitations under the license.
|
||||
|
||||
************************************************************************************/
|
||||
|
||||
Shader "Custom/ColumnGlow"
|
||||
{
|
||||
Properties
|
||||
{
|
||||
_TintColor ("Tint Color", Color) = (0.5,0.5,0.5,0.5)
|
||||
_Thickness("Thickness", Range(0, 1)) = 0.5
|
||||
_FadeStart("Fade Start", Range(0, 1)) = 0.5
|
||||
_FadeEnd("Fade End", Range(-1, 1)) = 0.5
|
||||
_Intensity("Intensity", Range(0, 1)) = 0.5
|
||||
|
||||
}
|
||||
SubShader
|
||||
{
|
||||
Tags { "RenderType"="Transparent" "IgnoreProjector"="True" "Queue"="Transparent" }
|
||||
Blend SrcAlpha One
|
||||
Cull Off Lighting Off ZWrite On
|
||||
|
||||
LOD 0
|
||||
|
||||
Pass
|
||||
{
|
||||
CGPROGRAM
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
// make fog work
|
||||
|
||||
|
||||
#include "UnityCG.cginc"
|
||||
|
||||
struct appdata
|
||||
{
|
||||
float4 vertex : POSITION;
|
||||
float4 normal : NORMAL;
|
||||
float2 uv : TEXCOORD0;
|
||||
};
|
||||
|
||||
struct v2f
|
||||
{
|
||||
float2 uv : TEXCOORD0;
|
||||
float4 vertex : SV_POSITION;
|
||||
float3 normal : NORMAL;
|
||||
float3 origPosition : POSITION1;
|
||||
float3 eyeDir : DIRECTION;
|
||||
};
|
||||
|
||||
fixed4 _TintColor;
|
||||
float _Thickness;
|
||||
float _FadeStart;
|
||||
float _FadeEnd;
|
||||
float _Intensity;
|
||||
|
||||
|
||||
|
||||
v2f vert (appdata v)
|
||||
{
|
||||
v2f o;
|
||||
UNITY_INITIALIZE_OUTPUT(v2f, o);
|
||||
o.vertex = UnityObjectToClipPos(v.vertex);
|
||||
o.normal = normalize(mul(UNITY_MATRIX_IT_MV,v.normal).xyz);
|
||||
o.origPosition = v.vertex;
|
||||
o.eyeDir = -normalize(UnityObjectToViewPos(v.vertex).xyz);
|
||||
//o.uv = TRANSFORM_TEX(v.uv, _MainTex);
|
||||
return o;
|
||||
}
|
||||
|
||||
fixed4 frag (v2f i) : SV_Target
|
||||
{
|
||||
float d = dot(i.normal,i.eyeDir);
|
||||
float p = smoothstep (0,_Thickness,dot(i.normal,i.eyeDir)) * smoothstep(_FadeStart,_FadeEnd,i.origPosition.y);
|
||||
return float4((p * _TintColor * _Intensity).xyz,p) ;
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 25bc671e448181c4fab3e6f52fb9d4bd
|
||||
timeCreated: 1446211200
|
||||
licenseType: Store
|
||||
ShaderImporter:
|
||||
defaultTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,127 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!21 &2100000
|
||||
Material:
|
||||
serializedVersion: 6
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_Name: MeterGrid
|
||||
m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_ShaderKeywords: _EMISSION
|
||||
m_LightmapFlags: 1
|
||||
m_CustomRenderQueue: -1
|
||||
stringTagMap: {}
|
||||
m_SavedProperties:
|
||||
serializedVersion: 2
|
||||
m_TexEnvs:
|
||||
- first:
|
||||
name: _BumpMap
|
||||
second:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- first:
|
||||
name: _DetailAlbedoMap
|
||||
second:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- first:
|
||||
name: _DetailMask
|
||||
second:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- first:
|
||||
name: _DetailNormalMap
|
||||
second:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- first:
|
||||
name: _EmissionMap
|
||||
second:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- first:
|
||||
name: _MainTex
|
||||
second:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- first:
|
||||
name: _MetallicGlossMap
|
||||
second:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- first:
|
||||
name: _OcclusionMap
|
||||
second:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- first:
|
||||
name: _ParallaxMap
|
||||
second:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_Floats:
|
||||
- first:
|
||||
name: _BumpScale
|
||||
second: 1
|
||||
- first:
|
||||
name: _Cutoff
|
||||
second: 0.5
|
||||
- first:
|
||||
name: _DetailNormalMapScale
|
||||
second: 1
|
||||
- first:
|
||||
name: _DstBlend
|
||||
second: 0
|
||||
- first:
|
||||
name: _GlossMapScale
|
||||
second: 1
|
||||
- first:
|
||||
name: _Glossiness
|
||||
second: 0.5
|
||||
- first:
|
||||
name: _GlossyReflections
|
||||
second: 1
|
||||
- first:
|
||||
name: _Metallic
|
||||
second: 0
|
||||
- first:
|
||||
name: _Mode
|
||||
second: 0
|
||||
- first:
|
||||
name: _OcclusionStrength
|
||||
second: 1
|
||||
- first:
|
||||
name: _Parallax
|
||||
second: 0.02
|
||||
- first:
|
||||
name: _SmoothnessTextureChannel
|
||||
second: 0
|
||||
- first:
|
||||
name: _SpecularHighlights
|
||||
second: 1
|
||||
- first:
|
||||
name: _SrcBlend
|
||||
second: 1
|
||||
- first:
|
||||
name: _UVSec
|
||||
second: 0
|
||||
- first:
|
||||
name: _ZWrite
|
||||
second: 1
|
||||
m_Colors:
|
||||
- first:
|
||||
name: _Color
|
||||
second: {r: 1, g: 1, b: 1, a: 1}
|
||||
- first:
|
||||
name: _EmissionColor
|
||||
second: {r: 0, g: 0, b: 0, a: 1}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 912cbad78358a1d48b357480224f4ad9
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.8 KiB |
@@ -0,0 +1,76 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 94201fda3ed62c94fbb0e4bf717756ba
|
||||
TextureImporter:
|
||||
fileIDToRecycleName: {}
|
||||
externalObjects: {}
|
||||
serializedVersion: 4
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 1
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
isReadable: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: -1
|
||||
aniso: -1
|
||||
mipBias: -1
|
||||
wrapU: -1
|
||||
wrapV: -1
|
||||
wrapW: -1
|
||||
nPOTScale: 1
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 0
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 0
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 0
|
||||
textureShape: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
platformSettings:
|
||||
- buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
spritePackingTag:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,76 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!21 &2100000
|
||||
Material:
|
||||
serializedVersion: 6
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_Name: TeleportLaser
|
||||
m_Shader: {fileID: 10755, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_ShaderKeywords: _EMISSION
|
||||
m_LightmapFlags: 1
|
||||
m_EnableInstancingVariants: 0
|
||||
m_DoubleSidedGI: 0
|
||||
m_CustomRenderQueue: -1
|
||||
stringTagMap: {}
|
||||
disabledShaderPasses: []
|
||||
m_SavedProperties:
|
||||
serializedVersion: 3
|
||||
m_TexEnvs:
|
||||
- _BumpMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailAlbedoMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailMask:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailNormalMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _EmissionMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _MainTex:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _MetallicGlossMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _OcclusionMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _ParallaxMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_Floats:
|
||||
- _BumpScale: 1
|
||||
- _Cutoff: 0.5
|
||||
- _DetailNormalMapScale: 1
|
||||
- _DstBlend: 0
|
||||
- _GlossMapScale: 1
|
||||
- _Glossiness: 0.5
|
||||
- _GlossyReflections: 1
|
||||
- _Metallic: 0
|
||||
- _Mode: 0
|
||||
- _OcclusionStrength: 1
|
||||
- _Parallax: 0.02
|
||||
- _SmoothnessTextureChannel: 0
|
||||
- _SpecularHighlights: 1
|
||||
- _SrcBlend: 1
|
||||
- _UVSec: 0
|
||||
- _ZWrite: 1
|
||||
m_Colors:
|
||||
- _Color: {r: 0, g: 1, b: 0, a: 1}
|
||||
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a379cec2ba497874788d17eb312c61be
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,76 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!21 &2100000
|
||||
Material:
|
||||
serializedVersion: 6
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_Name: lambert1
|
||||
m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_ShaderKeywords: _EMISSION
|
||||
m_LightmapFlags: 1
|
||||
m_EnableInstancingVariants: 0
|
||||
m_DoubleSidedGI: 0
|
||||
m_CustomRenderQueue: -1
|
||||
stringTagMap: {}
|
||||
disabledShaderPasses: []
|
||||
m_SavedProperties:
|
||||
serializedVersion: 3
|
||||
m_TexEnvs:
|
||||
- _BumpMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailAlbedoMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailMask:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailNormalMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _EmissionMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _MainTex:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _MetallicGlossMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _OcclusionMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _ParallaxMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_Floats:
|
||||
- _BumpScale: 1
|
||||
- _Cutoff: 0.5
|
||||
- _DetailNormalMapScale: 1
|
||||
- _DstBlend: 0
|
||||
- _GlossMapScale: 1
|
||||
- _Glossiness: 0.5
|
||||
- _GlossyReflections: 1
|
||||
- _Metallic: 0
|
||||
- _Mode: 0
|
||||
- _OcclusionStrength: 1
|
||||
- _Parallax: 0.02
|
||||
- _SmoothnessTextureChannel: 0
|
||||
- _SpecularHighlights: 1
|
||||
- _SrcBlend: 1
|
||||
- _UVSec: 0
|
||||
- _ZWrite: 1
|
||||
m_Colors:
|
||||
- _Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 24774b6e918e3c24a833857353a28b1b
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cb38391237052be4a8baf943256b1db2
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Binary file not shown.
+98
@@ -0,0 +1,98 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 823dc0eb5b064e14da00166d21f93fef
|
||||
ModelImporter:
|
||||
serializedVersion: 22
|
||||
fileIDToRecycleName:
|
||||
100000: //RootNode
|
||||
100002: Orientation
|
||||
100004: Position
|
||||
400000: //RootNode
|
||||
400002: Orientation
|
||||
400004: Position
|
||||
2100000: lambert1
|
||||
2300000: Orientation
|
||||
2300002: Position
|
||||
3300000: Orientation
|
||||
3300002: Position
|
||||
4300000: Position
|
||||
4300002: Orientation
|
||||
externalObjects: {}
|
||||
materials:
|
||||
importMaterials: 1
|
||||
materialName: 0
|
||||
materialSearch: 1
|
||||
materialLocation: 1
|
||||
animations:
|
||||
legacyGenerateAnimations: 4
|
||||
bakeSimulation: 0
|
||||
resampleCurves: 1
|
||||
optimizeGameObjects: 0
|
||||
motionNodeName:
|
||||
rigImportErrors:
|
||||
rigImportWarnings:
|
||||
animationImportErrors:
|
||||
animationImportWarnings:
|
||||
animationRetargetingWarnings:
|
||||
animationDoRetargetingWarnings: 0
|
||||
importAnimatedCustomProperties: 0
|
||||
animationCompression: 1
|
||||
animationRotationError: 0.5
|
||||
animationPositionError: 0.5
|
||||
animationScaleError: 0.5
|
||||
animationWrapMode: 0
|
||||
extraExposedTransformPaths: []
|
||||
extraUserProperties: []
|
||||
clipAnimations: []
|
||||
isReadable: 1
|
||||
meshes:
|
||||
lODScreenPercentages: []
|
||||
globalScale: 1
|
||||
meshCompression: 0
|
||||
addColliders: 0
|
||||
importVisibility: 1
|
||||
importBlendShapes: 1
|
||||
importCameras: 1
|
||||
importLights: 1
|
||||
swapUVChannels: 0
|
||||
generateSecondaryUV: 0
|
||||
useFileUnits: 1
|
||||
optimizeMeshForGPU: 1
|
||||
keepQuads: 0
|
||||
weldVertices: 1
|
||||
preserveHierarchy: 0
|
||||
indexFormat: 0
|
||||
secondaryUVAngleDistortion: 8
|
||||
secondaryUVAreaDistortion: 15.000001
|
||||
secondaryUVHardAngle: 88
|
||||
secondaryUVPackMargin: 4
|
||||
useFileScale: 1
|
||||
tangentSpace:
|
||||
normalSmoothAngle: 60
|
||||
normalImportMode: 0
|
||||
tangentImportMode: 3
|
||||
normalCalculationMode: 4
|
||||
importAnimation: 1
|
||||
copyAvatar: 0
|
||||
humanDescription:
|
||||
serializedVersion: 2
|
||||
human: []
|
||||
skeleton: []
|
||||
armTwist: 0.5
|
||||
foreArmTwist: 0.5
|
||||
upperLegTwist: 0.5
|
||||
legTwist: 0.5
|
||||
armStretch: 0.05
|
||||
legStretch: 0.05
|
||||
feetSpacing: 0
|
||||
rootMotionBoneName:
|
||||
rootMotionBoneRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
hasTranslationDoF: 0
|
||||
hasExtraRoot: 0
|
||||
skeletonHasParents: 1
|
||||
lastHumanDescriptionAvatarSource: {instanceID: 0}
|
||||
animationType: 0
|
||||
humanoidOversampling: 1
|
||||
additionalBone: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 522b89d0f09cc834db5f015f40e578f3
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: babf73c2d8b61ea46b4e878001ebc6d7
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,229 @@
|
||||
/************************************************************************************
|
||||
|
||||
See SampleFramework license.txt for license terms. Unless required by applicable law
|
||||
or agreed to in writing, the sample code is provided "AS IS" WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied. See the license for specific
|
||||
language governing permissions and limitations under the license.
|
||||
|
||||
************************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// This component is responsible for moving the character capsule to match the HMD, fading out the camera or blocking movement when
|
||||
/// collisions occur, and adjusting the character capsule height to match the HMD's offset from the ground.
|
||||
/// </summary>
|
||||
public class CharacterCameraConstraint : MonoBehaviour
|
||||
{
|
||||
// Distance in front of the camera at which fading begins.
|
||||
private const float FADE_RAY_LENGTH = 0.25f;
|
||||
|
||||
// How much overlap before fully faded.
|
||||
private const float FADE_OVERLAP_MAXIMUM = 0.1f;
|
||||
|
||||
// Fully faded amount, which can be adjusted for debugging purposes.
|
||||
private const float FADE_AMOUNT_MAXIMUM = 1.0f;
|
||||
|
||||
/// <summary>
|
||||
/// This should be a reference to the OVRCameraRig that is usually a child of the PlayerController.
|
||||
/// </summary>
|
||||
[Tooltip("This should be a reference to the OVRCameraRig that is usually a child of the PlayerController.")]
|
||||
public OVRCameraRig CameraRig;
|
||||
|
||||
/// <summary>
|
||||
/// Collision layers to be used for the purposes of fading out the screen when the HMD is inside world
|
||||
/// geometry and adjusting the capsule height.
|
||||
/// </summary>
|
||||
[Tooltip("Collision layers to be used for the purposes of fading out the screen when the HMD is inside world " +
|
||||
"geometry and adjusting the capsule height.")]
|
||||
public LayerMask CollideLayers;
|
||||
|
||||
/// <summary>
|
||||
/// Offset is added to camera's real world height, effectively treating it as though the player was
|
||||
/// taller/standing higher.
|
||||
/// </summary>
|
||||
[Tooltip("Offset is added to camera's real world height, effectively treating it as though the player was " +
|
||||
"taller/standing higher.")]
|
||||
public float HeightOffset;
|
||||
|
||||
/// <summary>
|
||||
/// Minimum height that the character capsule can shrink to. To disable, set to capsule's height.
|
||||
/// </summary>
|
||||
[Tooltip("Minimum height that the character capsule can shrink to. To disable, set to capsule's height.")]
|
||||
public float MinimumHeight;
|
||||
|
||||
/// <summary>
|
||||
/// Maximum height that the character capsule can grow to. To disable, set to capsule's height.
|
||||
/// </summary>
|
||||
[Tooltip("Maximum height that the character capsule can grow to. To disable, set to capsule's height.")]
|
||||
public float MaximumHeight;
|
||||
|
||||
private CapsuleCollider _character;
|
||||
private SimpleCapsuleWithStickMovement _simplePlayerController;
|
||||
|
||||
CharacterCameraConstraint()
|
||||
{
|
||||
}
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
_character = GetComponent<CapsuleCollider>();
|
||||
_simplePlayerController = GetComponent<SimpleCapsuleWithStickMovement>();
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
_simplePlayerController.CameraUpdated += CameraUpdate;
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
_simplePlayerController.CameraUpdated -= CameraUpdate;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This method is the handler for the PlayerController.CameraUpdated event, which is used
|
||||
/// to handle whether or not the screen should fade out due to the camera's position (such
|
||||
/// as in a wall), and update the character height based on camera position.
|
||||
///
|
||||
/// Future work: Have the character capsule attempt to match the camera's X,Z position so
|
||||
/// that hit detection and dodging work as expected. Presently the capsule only grows up
|
||||
/// and down, but doesn't otherwise change based on camera position.
|
||||
/// </summary>
|
||||
private void CameraUpdate()
|
||||
{
|
||||
// Check whether the camera is inside of geometry or on the other side of geometry.
|
||||
// Then check if any geometry would be clipped. Fade out screen accordingly.
|
||||
float clippingOverlap = 0.0f;
|
||||
if (CheckCameraOverlapped())
|
||||
{
|
||||
OVRScreenFade.instance.SetExplicitFade(FADE_AMOUNT_MAXIMUM);
|
||||
}
|
||||
else if (CheckCameraNearClipping(out clippingOverlap))
|
||||
{
|
||||
// Calculate a `t` value based on where in the interval [0.0, FADE_OVERLAP_MAXIMUM]
|
||||
// that our actual overlap lies, and then use that `t` value to calulate an
|
||||
// actual fade amount on the interval [0.0, FADE_AMOUNT_MAXIMUM].
|
||||
// Note: Both math helper functions clamp `t` to within [0.0, 1.0].
|
||||
float fadeParameter = Mathf.InverseLerp(0.0f, FADE_OVERLAP_MAXIMUM, clippingOverlap);
|
||||
float fadeAlpha = Mathf.Lerp(0.0f, FADE_AMOUNT_MAXIMUM, fadeParameter);
|
||||
OVRScreenFade.instance.SetExplicitFade(fadeAlpha);
|
||||
}
|
||||
else
|
||||
{
|
||||
OVRScreenFade.instance.SetExplicitFade(0.0f);
|
||||
}
|
||||
|
||||
// Offset the camera into the capsule that's used so that it doesn't scrape any
|
||||
// overhanging geometry that the player can barely fit through. Currently just
|
||||
// based on where we start fading.
|
||||
float capsuleOffset = FADE_RAY_LENGTH;
|
||||
|
||||
// Calculate the current height by re-adding the height offset to the camera
|
||||
// position.
|
||||
float calculatedHeight = CameraRig.centerEyeAnchor.localPosition.y + HeightOffset + capsuleOffset;
|
||||
|
||||
// Calculate the minimum allowable capsule height, based on the current value, and
|
||||
// the configured minimum value. Current height is always a valid value to ensure
|
||||
// we don't change the capsule height for any reason other than the camera position
|
||||
// changing.
|
||||
float calculatedMinimumHeight = MinimumHeight;
|
||||
calculatedMinimumHeight = Mathf.Min(_character.height, calculatedMinimumHeight);
|
||||
|
||||
// Calculate the maximum allowable capsule height, based on the current value, the
|
||||
// configured maximum value and whether there is something overhead. Current
|
||||
// height is always a valid value to ensure we don't change the capsule height for
|
||||
// any reason other than the camera position changing.
|
||||
float calculatedMaximumHeight = MaximumHeight;
|
||||
RaycastHit heightHitInfo;
|
||||
if (Physics.SphereCast(_character.transform.position, _character.radius * 0.2f, Vector3.up, out heightHitInfo,
|
||||
MaximumHeight - _character.transform.position.y, CollideLayers, QueryTriggerInteraction.Ignore))
|
||||
{
|
||||
calculatedMaximumHeight = heightHitInfo.point.y;
|
||||
}
|
||||
|
||||
calculatedMaximumHeight = Mathf.Max(_character.height, calculatedMaximumHeight);
|
||||
|
||||
// Finally adjust capsule height based on camera position, clamped to our acceptable
|
||||
// minimum and maximum values.
|
||||
_character.height = Mathf.Clamp(calculatedHeight, calculatedMinimumHeight, calculatedMaximumHeight);
|
||||
|
||||
// Offset the height of the camera to account for the changing capsule height.
|
||||
// We want to select a height offset that places the camera near the top of the
|
||||
// capsule. We offset the camera down from the top of the capsule to prevent
|
||||
// the screen from fading while the capsule barely fits under an overhang.
|
||||
float cameraRigHeightOffset = HeightOffset - (_character.height * 0.5f) - capsuleOffset;
|
||||
CameraRig.transform.localPosition = new Vector3(0.0f, cameraRigHeightOffset, 0.0f);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This method checks whether the camera is inside of geometry or has geometry between it
|
||||
/// and the character's capsule.
|
||||
/// </summary>
|
||||
private bool CheckCameraOverlapped()
|
||||
{
|
||||
Camera camera = CameraRig.centerEyeAnchor.GetComponent<Camera>();
|
||||
|
||||
// Use a ray from the capsule starting at the camera's height, but clamped
|
||||
// to make sure it comes from the capsule. We clamp slightly inside of
|
||||
// the capsule to account for the sphere cast radius and a small offset
|
||||
// in case things would otherwise be touching.
|
||||
Vector3 origin = _character.transform.position;
|
||||
float yOffset = Mathf.Max(0.0f, (_character.height * 0.5f) - camera.nearClipPlane - 0.01f);
|
||||
origin.y = Mathf.Clamp(CameraRig.centerEyeAnchor.position.y, _character.transform.position.y - yOffset,
|
||||
_character.transform.position.y + yOffset);
|
||||
Vector3 delta = CameraRig.centerEyeAnchor.position - origin;
|
||||
float distance = delta.magnitude;
|
||||
Vector3 direction = delta / distance;
|
||||
RaycastHit hitInfo;
|
||||
return Physics.SphereCast(origin, camera.nearClipPlane, direction, out hitInfo, distance, CollideLayers,
|
||||
QueryTriggerInteraction.Ignore);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This method checks whether the camera is close enough to geometry to
|
||||
/// cause it to start clipping, and if so, return the overlap amount.
|
||||
/// </summary>
|
||||
private bool CheckCameraNearClipping(out float result)
|
||||
{
|
||||
Camera camera = CameraRig.centerEyeAnchor.GetComponent<Camera>();
|
||||
|
||||
Vector3[] frustumCorners = new Vector3[4];
|
||||
camera.CalculateFrustumCorners(new Rect(0, 0, 1, 1), camera.nearClipPlane, Camera.MonoOrStereoscopicEye.Mono,
|
||||
frustumCorners);
|
||||
|
||||
// Cast a ray through each corner of the frustum and the center, and take the
|
||||
// maximum overlap (if any) returned as the basis to decide how much to fade.
|
||||
Vector3 frustumBottomLeft = CameraRig.centerEyeAnchor.position +
|
||||
(Vector3.Normalize(CameraRig.centerEyeAnchor.TransformVector(frustumCorners[0])) *
|
||||
FADE_RAY_LENGTH);
|
||||
Vector3 frustumTopLeft = CameraRig.centerEyeAnchor.position +
|
||||
(Vector3.Normalize(CameraRig.centerEyeAnchor.TransformVector(frustumCorners[1])) *
|
||||
FADE_RAY_LENGTH);
|
||||
Vector3 frustumTopRight = CameraRig.centerEyeAnchor.position +
|
||||
(Vector3.Normalize(CameraRig.centerEyeAnchor.TransformVector(frustumCorners[2])) *
|
||||
FADE_RAY_LENGTH);
|
||||
Vector3 frustumBottomRight = CameraRig.centerEyeAnchor.position +
|
||||
(Vector3.Normalize(CameraRig.centerEyeAnchor.TransformVector(frustumCorners[3])) *
|
||||
FADE_RAY_LENGTH);
|
||||
Vector3 frustumCenter = (frustumTopLeft + frustumBottomRight) / 2.0f;
|
||||
|
||||
bool hit = false;
|
||||
result = 0.0f;
|
||||
foreach (Vector3 frustumPoint in new Vector3[]
|
||||
{ frustumBottomLeft, frustumTopLeft, frustumTopRight, frustumBottomRight, frustumCenter })
|
||||
{
|
||||
RaycastHit hitInfo;
|
||||
if (Physics.Linecast(CameraRig.centerEyeAnchor.position, frustumPoint, out hitInfo, CollideLayers,
|
||||
QueryTriggerInteraction.Ignore))
|
||||
{
|
||||
hit = true;
|
||||
result = Mathf.Max(result, Vector3.Distance(hitInfo.point, frustumPoint));
|
||||
}
|
||||
}
|
||||
|
||||
return hit;
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cf162022e230bb745ab2ec48cd357f9e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6d30e31160d61eb41b8da147dbb00455
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
/************************************************************************************
|
||||
|
||||
See SampleFramework license.txt for license terms. Unless required by applicable law
|
||||
or agreed to in writing, the sample code is provided "AS IS" WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied. See the license for specific
|
||||
language governing permissions and limitations under the license.
|
||||
|
||||
************************************************************************************/
|
||||
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
using System.Linq;
|
||||
using UnityEditor;
|
||||
|
||||
[CustomEditor(typeof(TeleportTransitionWarp))]
|
||||
public class TeleportTransitionWarpInspector : Editor
|
||||
{
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
base.OnInspectorGUI();
|
||||
|
||||
var warp = (TeleportTransitionWarp)target;
|
||||
|
||||
warp.PositionLerp = EditorGUILayout.CurveField("Position Lerp", warp.PositionLerp, GUILayout.Height(50));
|
||||
|
||||
GUILayout.BeginHorizontal();
|
||||
GUILayout.Label("Position Lerp Modes");
|
||||
if (GUILayout.Button("Default"))
|
||||
{
|
||||
warp.PositionLerp = AnimationCurve.Linear(0, 0, 1, 1);
|
||||
}
|
||||
|
||||
if (GUILayout.Button("Ease"))
|
||||
{
|
||||
warp.PositionLerp = AnimationCurve.EaseInOut(0, 0, 1, 1);
|
||||
}
|
||||
|
||||
if (GUILayout.Button("Step 5"))
|
||||
{
|
||||
CreateStep(warp, 5);
|
||||
}
|
||||
|
||||
if (GUILayout.Button("Step 10"))
|
||||
{
|
||||
CreateStep(warp, 10);
|
||||
}
|
||||
|
||||
GUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
void CreateStep(TeleportTransitionWarp warp, int count)
|
||||
{
|
||||
Keyframe[] keys = new Keyframe[count + 1];
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
keys[i] = new Keyframe((float)i / (count), (i + 1.0f) / count);
|
||||
}
|
||||
|
||||
keys[count] = new Keyframe(1, 1);
|
||||
warp.PositionLerp = new AnimationCurve(keys);
|
||||
for (int i = 0; i < count + 1; i++)
|
||||
{
|
||||
AnimationUtility.SetKeyLeftTangentMode(warp.PositionLerp, i, AnimationUtility.TangentMode.Constant);
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3be20267c2de05e4487484be14e69924
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,57 @@
|
||||
/************************************************************************************
|
||||
|
||||
See SampleFramework license.txt for license terms. Unless required by applicable law
|
||||
or agreed to in writing, the sample code is provided "AS IS" WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied. See the license for specific
|
||||
language governing permissions and limitations under the license.
|
||||
|
||||
************************************************************************************/
|
||||
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
using JetBrains.Annotations;
|
||||
using UnityEngine.Assertions;
|
||||
#if UNITY_EDITOR
|
||||
using UnityEngine.SceneManagement;
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Simply aggregates accessors.
|
||||
/// </summary>
|
||||
public class LocomotionController : MonoBehaviour
|
||||
{
|
||||
public OVRCameraRig CameraRig;
|
||||
|
||||
//public CharacterController CharacterController;
|
||||
public CapsuleCollider CharacterController;
|
||||
|
||||
//public OVRPlayerController PlayerController;
|
||||
public SimpleCapsuleWithStickMovement PlayerController;
|
||||
|
||||
void Start()
|
||||
{
|
||||
/*
|
||||
if (CharacterController == null)
|
||||
{
|
||||
CharacterController = GetComponentInParent<CharacterController>();
|
||||
}
|
||||
Assert.IsNotNull(CharacterController);
|
||||
*/
|
||||
//if (PlayerController == null)
|
||||
//{
|
||||
//PlayerController = GetComponentInParent<OVRPlayerController>();
|
||||
//}
|
||||
//Assert.IsNotNull(PlayerController);
|
||||
if (CameraRig == null)
|
||||
{
|
||||
CameraRig = FindObjectOfType<OVRCameraRig>();
|
||||
}
|
||||
|
||||
Assert.IsNotNull(CameraRig);
|
||||
#if UNITY_EDITOR
|
||||
OVRPlugin.SendEvent("locomotion_controller", (SceneManager.GetActiveScene().name == "Locomotion").ToString(),
|
||||
"sample_framework");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 085d9ec7bb5e55f48b879d93931f553e
|
||||
timeCreated: 1491849913
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,888 @@
|
||||
/************************************************************************************
|
||||
|
||||
See SampleFramework license.txt for license terms. Unless required by applicable law
|
||||
or agreed to in writing, the sample code is provided "AS IS" WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied. See the license for specific
|
||||
language governing permissions and limitations under the license.
|
||||
|
||||
************************************************************************************/
|
||||
|
||||
// Enable DEBUG_TELEPORT_STATES to cause messages to be logged when teleport state changes occur.
|
||||
//#define DEBUG_TELEPORT_STATES
|
||||
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using UnityEngine.EventSystems;
|
||||
using Debug = UnityEngine.Debug;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The LocomotionTeleport class controls and centralizes functionality for the various types
|
||||
/// of teleports. The system is designed to work as a set of components that are each responsible
|
||||
/// for different aspects of the teleport process. This makes it possible for different kinds of
|
||||
/// teleport behaviors to be occur by simply enabling different combinations of components.
|
||||
/// </summary>
|
||||
public class LocomotionTeleport : MonoBehaviour
|
||||
{
|
||||
/// <summary>
|
||||
/// The process of teleporting is represented by a simple state machine, and each of the
|
||||
/// possible states are represented by this enum.
|
||||
/// </summary>
|
||||
public enum States
|
||||
{
|
||||
Ready,
|
||||
Aim,
|
||||
CancelAim,
|
||||
PreTeleport,
|
||||
CancelTeleport,
|
||||
Teleporting,
|
||||
PostTeleport
|
||||
}
|
||||
|
||||
#region Linear movement control booleans.
|
||||
|
||||
/// <summary>
|
||||
/// Allow linear movement prior to the teleport system being activated.
|
||||
/// </summary>
|
||||
[Tooltip("Allow linear movement prior to the teleport system being activated.")]
|
||||
public bool EnableMovementDuringReady = true;
|
||||
|
||||
/// <summary>
|
||||
/// Allow linear movement while the teleport system is in the process of aiming for a teleport target.
|
||||
/// </summary>
|
||||
[Tooltip("Allow linear movement while the teleport system is in the process of aiming for a teleport target.")]
|
||||
public bool EnableMovementDuringAim = true;
|
||||
|
||||
/// <summary>
|
||||
/// Allow linear movement while the teleport system is in the process of configuring
|
||||
/// the landing orientation.
|
||||
/// </summary>
|
||||
[Tooltip("Allow linear movement while the teleport system is in the process of configuring " +
|
||||
"the landing orientation.")]
|
||||
public bool EnableMovementDuringPreTeleport = true;
|
||||
|
||||
/// <summary>
|
||||
/// Allow linear movement after the teleport has occurred but before the system has returned to
|
||||
/// the ready state.
|
||||
/// </summary>
|
||||
[Tooltip("Allow linear movement after the teleport has occurred but before the system has returned to " +
|
||||
"the ready state.")]
|
||||
public bool EnableMovementDuringPostTeleport = true;
|
||||
|
||||
/// <summary>
|
||||
/// Helper function to enable linear movement during the various teleport states.
|
||||
/// Movement may not be desired at all states, for instance during aiming it may be preferred to prevent movement to allow a
|
||||
/// thumbstick to be used for choosing the landing orientation.
|
||||
/// </summary>
|
||||
/// <param name="ready"></param>
|
||||
/// <param name="aim"></param>
|
||||
/// <param name="pre"></param>
|
||||
/// <param name="post"></param>
|
||||
public void EnableMovement(bool ready, bool aim, bool pre, bool post)
|
||||
{
|
||||
EnableMovementDuringReady = ready;
|
||||
EnableMovementDuringAim = aim;
|
||||
EnableMovementDuringPreTeleport = pre;
|
||||
EnableMovementDuringPostTeleport = post;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Rotation control booleans.
|
||||
|
||||
/// <summary>
|
||||
/// Allow rotation prior to the teleport system being activated.
|
||||
/// </summary>
|
||||
[Tooltip("Allow rotation prior to the teleport system being activated.")]
|
||||
public bool EnableRotationDuringReady = true;
|
||||
|
||||
/// <summary>
|
||||
/// Allow rotation while the teleport system is in the process of aiming for a teleport target.
|
||||
/// </summary>
|
||||
[Tooltip("Allow rotation while the teleport system is in the process of aiming for a teleport target.")]
|
||||
public bool EnableRotationDuringAim = true;
|
||||
|
||||
/// <summary>
|
||||
/// Allow rotation while the teleport system is in the process of configuring the landing orientation.
|
||||
/// </summary>
|
||||
[Tooltip("Allow rotation while the teleport system is in the process of configuring the landing orientation.")]
|
||||
public bool EnableRotationDuringPreTeleport = true;
|
||||
|
||||
/// <summary>
|
||||
/// Allow rotation after the teleport has occurred but before the system has returned to the ready state.
|
||||
/// </summary>
|
||||
[Tooltip("Allow rotation after the teleport has occurred but before the system has returned to the ready state.")]
|
||||
public bool EnableRotationDuringPostTeleport = true;
|
||||
|
||||
/// <summary>
|
||||
/// Helper function to enable rotation movement during the various teleport states.
|
||||
/// Rotation may not be desired at all states, for instance during aiming it may be preferred to prevent rotation (snap turn or linear)
|
||||
/// to prevent the camera from being rotated while preparing to teleport.
|
||||
/// </summary>
|
||||
/// <param name="ready"></param>
|
||||
/// <param name="aim"></param>
|
||||
/// <param name="pre"></param>
|
||||
/// <param name="post"></param>
|
||||
public void EnableRotation(bool ready, bool aim, bool pre, bool post)
|
||||
{
|
||||
EnableRotationDuringReady = ready;
|
||||
EnableRotationDuringAim = aim;
|
||||
EnableRotationDuringPreTeleport = pre;
|
||||
EnableRotationDuringPostTeleport = post;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// The current state of the teleport state machine.
|
||||
/// </summary>
|
||||
public States CurrentState { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Aiming is handled by one specific aim handler at a time. When the aim handler component is enabled, it
|
||||
/// will set this reference to the AimHandler so that other parts of the system which need access to the
|
||||
/// current aim handler can be sure to use the correct component.
|
||||
/// </summary>
|
||||
[NonSerialized]
|
||||
public TeleportAimHandler AimHandler;
|
||||
|
||||
/// <summary>
|
||||
/// This prefab will be instantiated as needed and updated to match the current aim target.
|
||||
/// </summary>
|
||||
[Tooltip("This prefab will be instantiated as needed and updated to match the current aim target.")]
|
||||
public TeleportDestination TeleportDestinationPrefab;
|
||||
|
||||
[Tooltip("TeleportDestinationPrefab will be instantiated into this layer.")]
|
||||
public int TeleportDestinationLayer = 0;
|
||||
|
||||
#region Support Events
|
||||
|
||||
/// <summary>
|
||||
/// This event is raised when the teleport destination is in the process of being updated. It is used by the active TeleportDestination
|
||||
/// to update it's visual state, position and orientation indicator to match the results of the teleport aim and targeting system.
|
||||
/// </summary>
|
||||
public event Action<bool, Vector3?, Quaternion?, Quaternion?> UpdateTeleportDestination;
|
||||
|
||||
/// <summary>
|
||||
/// When the active aim and orientation handler finishes preparing the data for the teleport destination, this method will be called
|
||||
/// in order to raise the UpdateTeleportDestination event, which will in turn give any active teleport destination objects an opportunity
|
||||
/// to update their visual state accordingly.
|
||||
/// </summary>
|
||||
/// <param name="isValidDestination"></param>
|
||||
/// <param name="position"></param>
|
||||
/// <param name="rotation"></param>
|
||||
public void OnUpdateTeleportDestination(bool isValidDestination, Vector3? position, Quaternion? rotation,
|
||||
Quaternion? landingRotation)
|
||||
{
|
||||
if (UpdateTeleportDestination != null)
|
||||
{
|
||||
UpdateTeleportDestination(isValidDestination, position, rotation, landingRotation);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The TeleportInputHandler is responsible for converting input events to TeleportIntentions.
|
||||
/// </summary>
|
||||
[NonSerialized]
|
||||
public TeleportInputHandler InputHandler;
|
||||
|
||||
/// <summary>
|
||||
/// TeleportIntentions track what the TeleportState should attempt to transition to.
|
||||
/// </summary>
|
||||
public enum TeleportIntentions
|
||||
{
|
||||
None, // No teleport is requested.
|
||||
Aim, // The user wants to aim for a teleport.
|
||||
PreTeleport, // The user has selected a location to teleport, and the input handler will now control how long it stays in PreTeleport.
|
||||
Teleport // The user has chosen to teleport. If the destination is valid, the state will transition to Teleporting, otherwise it will switch to CancelTeleport.
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The CurrentIntention is used by the state machine to know when it is time to switch to a new state.
|
||||
/// </summary>
|
||||
[NonSerialized]
|
||||
public TeleportIntentions CurrentIntention;
|
||||
|
||||
/// <summary>
|
||||
/// The state machine will not exit the PreTeleport state while IsPreTeleportRequested is true.
|
||||
/// The sample doesn't currently use this, however this provides new components the ability to delay exiting
|
||||
/// the PreTeleport state until game logic is ready for it.
|
||||
/// </summary>
|
||||
[NonSerialized]
|
||||
public bool IsPreTeleportRequested;
|
||||
|
||||
/// <summary>
|
||||
/// The state machine will not exit the Teleporting state while IsTransitioning is true. This is how the BlinkTransition and WarpTransition
|
||||
/// force the system to remain in the Teleporting state until the transition is complete.
|
||||
/// </summary>
|
||||
[NonSerialized]
|
||||
public bool IsTransitioning;
|
||||
|
||||
/// <summary>
|
||||
/// The state machine will not exit the PostTeleport state while IsPostTeleportRequested is true.
|
||||
/// The sample doesn't currently use this, however this provides new components the ability to delay exiting
|
||||
/// the PostTeleport state until game logic is ready for it.
|
||||
/// </summary>
|
||||
[NonSerialized]
|
||||
public bool IsPostTeleportRequested;
|
||||
|
||||
/// <summary>
|
||||
/// Created at runtime, this gameobject is used to track where the player will teleport.
|
||||
/// The actual position depends on the type of Aim Handler and Target Handler that is active.
|
||||
/// Aim Handlers:
|
||||
/// * Laser: player capsule swept along aim ray until it hits terrain or valid target.
|
||||
/// * Parabolic: player capsule swept along a series of line segments approximating a parabolic curve until it hits terrain or valid target.
|
||||
/// Target Handlers:
|
||||
/// * NavMesh = Destination only valid if it lies within the nav mesh.
|
||||
/// * Node = Destination valid if within radius of a teleport node. Target is invalidated when aim leaves the node radius.
|
||||
/// * Physical = Any terrain is valid.
|
||||
/// </summary>
|
||||
private TeleportDestination _teleportDestination;
|
||||
|
||||
/// <summary>
|
||||
/// Returns the orientation of the current teleport destination's orientation indicator.
|
||||
/// </summary>
|
||||
public Quaternion DestinationRotation
|
||||
{
|
||||
get { return _teleportDestination.OrientationIndicator.rotation; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// The LocomotionController that is used by object to discover shared references.
|
||||
/// </summary>
|
||||
public LocomotionController LocomotionController { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The aiming system uses a common function for testing collision with the world, which can be configured to use different
|
||||
/// shapes for testing.
|
||||
/// </summary>
|
||||
public enum AimCollisionTypes
|
||||
{
|
||||
Point, // ray casting
|
||||
Sphere, // swept sphere test
|
||||
Capsule // swept capsule test, optionally sized to match the character controller dimensions.
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// When aiming at possible destinations, the aim collision type determines which shape to use
|
||||
/// for collision tests.
|
||||
/// </summary>
|
||||
[Tooltip("When aiming at possible destinations, the aim collision type determines which shape to use " +
|
||||
"for collision tests.")]
|
||||
public AimCollisionTypes AimCollisionType;
|
||||
|
||||
/// <summary>
|
||||
/// Use the character collision radius/height/skinwidth for sphere/capsule collision tests.
|
||||
/// </summary>
|
||||
[Tooltip("Use the character collision radius/height/skinwidth for sphere/capsule collision tests.")]
|
||||
public bool UseCharacterCollisionData;
|
||||
|
||||
/// <summary>
|
||||
/// Radius of the sphere or capsule used for collision testing when aiming to possible teleport destinations.
|
||||
/// Ignored if UseCharacterCollisionData is true.
|
||||
/// </summary>
|
||||
[Tooltip("Radius of the sphere or capsule used for collision testing when aiming to possible teleport " +
|
||||
"destinations. Ignored if UseCharacterCollisionData is true.")]
|
||||
public float AimCollisionRadius;
|
||||
|
||||
/// <summary>
|
||||
/// Height of the capsule used for collision testing when aiming to possible teleport destinations.
|
||||
/// Ignored if UseCharacterCollisionData is true.
|
||||
/// </summary>
|
||||
[Tooltip("Height of the capsule used for collision testing when aiming to possible teleport destinations. " +
|
||||
"Ignored if UseCharacterCollisionData is true.")]
|
||||
public float AimCollisionHeight;
|
||||
|
||||
/// <summary>
|
||||
/// AimCollisionTest is used by many of the aim handlers to standardize the testing of aiming beams. By choosing between the increasingly restrictive
|
||||
/// point, sphere and capsule tests, the aiming system can limit targeting to routes which are not physically blocked. For example, a sphere test
|
||||
/// is good for ensuring the player can't teleport through bars to get out of a jail cell.
|
||||
/// </summary>
|
||||
/// <param name="start"></param>
|
||||
/// <param name="end"></param>
|
||||
/// <param name="aimCollisionLayerMask"></param>
|
||||
/// <param name="hitInfo"></param>
|
||||
/// <returns></returns>
|
||||
public bool AimCollisionTest(Vector3 start, Vector3 end, LayerMask aimCollisionLayerMask, out RaycastHit hitInfo)
|
||||
{
|
||||
var delta = end - start;
|
||||
var distance = delta.magnitude;
|
||||
var direction = delta / distance;
|
||||
|
||||
switch (AimCollisionType)
|
||||
{
|
||||
case AimCollisionTypes.Capsule:
|
||||
{
|
||||
float r, h;
|
||||
if (UseCharacterCollisionData)
|
||||
{
|
||||
var c = LocomotionController.CharacterController;
|
||||
h = c.height;
|
||||
r = c.radius;
|
||||
}
|
||||
else
|
||||
{
|
||||
h = AimCollisionHeight;
|
||||
r = AimCollisionRadius;
|
||||
}
|
||||
|
||||
return Physics.CapsuleCast(start + new Vector3(0, r, 0),
|
||||
start + new Vector3(0, h + r, 0), r, direction,
|
||||
out hitInfo, distance, aimCollisionLayerMask, QueryTriggerInteraction.Ignore);
|
||||
}
|
||||
|
||||
case AimCollisionTypes.Point:
|
||||
return Physics.Raycast(start, direction, out hitInfo, distance, aimCollisionLayerMask,
|
||||
QueryTriggerInteraction.Ignore);
|
||||
|
||||
case AimCollisionTypes.Sphere:
|
||||
{
|
||||
float r;
|
||||
if (UseCharacterCollisionData)
|
||||
{
|
||||
var c = LocomotionController.CharacterController;
|
||||
//r = c.radius - c.skinWidth;
|
||||
r = c.radius;
|
||||
}
|
||||
else
|
||||
{
|
||||
r = AimCollisionRadius;
|
||||
}
|
||||
|
||||
return Physics.SphereCast(start, r, direction, out hitInfo, distance, aimCollisionLayerMask,
|
||||
QueryTriggerInteraction.Ignore);
|
||||
}
|
||||
}
|
||||
|
||||
// App should never get here.
|
||||
throw new Exception();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Internal logging function that is conditionally enabled via DEBUG_TELEPORT_STATES
|
||||
/// </summary>
|
||||
/// <param name="msg"></param>
|
||||
[Conditional("DEBUG_TELEPORT_STATES")]
|
||||
protected void LogState(string msg)
|
||||
{
|
||||
Debug.Log(Time.frameCount + ": " + msg);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is called whenever a new teleport destination is required. This might occur when rapidly switching
|
||||
/// between targets, or when teleporting multiple times in quick succession when the teleport destination
|
||||
/// requires additional time to complete any animations that are triggered by these actions.
|
||||
/// </summary>
|
||||
protected void CreateNewTeleportDestination()
|
||||
{
|
||||
// ensure the prefab isn't active in order to delay event handler setup until after it has been
|
||||
// configured with a reference to this object.
|
||||
TeleportDestinationPrefab.gameObject.SetActive(false);
|
||||
TeleportDestination td = GameObject.Instantiate(TeleportDestinationPrefab);
|
||||
td.LocomotionTeleport = this;
|
||||
td.gameObject.layer = TeleportDestinationLayer;
|
||||
_teleportDestination = td;
|
||||
_teleportDestination.LocomotionTeleport = this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Notify the teleport destination that it needs to deactivate.
|
||||
/// If the destination has event handlers hooked up, the destination game object may not be immediately deactivated
|
||||
/// in order to allow it to trigger animated effects.
|
||||
/// </summary>
|
||||
private void DeactivateDestination()
|
||||
{
|
||||
_teleportDestination.OnDeactivated();
|
||||
}
|
||||
|
||||
public void RecycleTeleportDestination(TeleportDestination oldDestination)
|
||||
{
|
||||
if (oldDestination == _teleportDestination)
|
||||
{
|
||||
CreateNewTeleportDestination();
|
||||
}
|
||||
|
||||
GameObject.Destroy(oldDestination.gameObject);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Each state has booleans that determine if linear motion or rotational motion is enabled for that state.
|
||||
/// This method is called when entering each state with the appropriate values.
|
||||
/// </summary>
|
||||
/// <param name="enableLinear"></param>
|
||||
/// <param name="enableRotation"></param>
|
||||
private void EnableMotion(bool enableLinear, bool enableRotation)
|
||||
{
|
||||
LocomotionController.PlayerController.EnableLinearMovement = enableLinear;
|
||||
LocomotionController.PlayerController.EnableRotation = enableRotation;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// When the component first wakes up, cache the LocomotionController and the initial
|
||||
/// TeleportDestination object.
|
||||
/// </summary>
|
||||
private void Awake()
|
||||
{
|
||||
LocomotionController = GetComponent<LocomotionController>();
|
||||
CreateNewTeleportDestination();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Start the state machine coroutines.
|
||||
/// </summary>
|
||||
public virtual void OnEnable()
|
||||
{
|
||||
CurrentState = States.Ready;
|
||||
StartCoroutine(ReadyStateCoroutine());
|
||||
}
|
||||
|
||||
public virtual void OnDisable()
|
||||
{
|
||||
StopAllCoroutines();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This event is raised when entering the Ready state. The initial use for this is for the input handler to start
|
||||
/// processing input in order to eventually set the TeleportIntention to Aim when the user requests it.
|
||||
/// </summary>
|
||||
public event Action EnterStateReady;
|
||||
|
||||
/// <summary>
|
||||
/// This coroutine will be running while the component is in the Ready state.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected IEnumerator ReadyStateCoroutine()
|
||||
{
|
||||
LogState("ReadyState: Start");
|
||||
|
||||
// yield once so that all the components will have time to process their OnEnable message before this
|
||||
// does work that relies on the events being hooked up.
|
||||
yield return null;
|
||||
|
||||
LogState("ReadyState: Ready");
|
||||
|
||||
CurrentState = States.Ready;
|
||||
EnableMotion(EnableMovementDuringReady, EnableRotationDuringReady);
|
||||
|
||||
if (EnterStateReady != null)
|
||||
{
|
||||
EnterStateReady();
|
||||
}
|
||||
|
||||
// Wait until a teleport is requested.
|
||||
while (CurrentIntention != TeleportIntentions.Aim)
|
||||
{
|
||||
yield return null;
|
||||
}
|
||||
|
||||
LogState("ReadyState: End");
|
||||
|
||||
// Wait until the next frame to proceed to the next state's coroutine.
|
||||
yield return null;
|
||||
|
||||
StartCoroutine(AimStateCoroutine());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The AimData contains data provided by the Aim Handler which represents the final set of points
|
||||
/// that were used for aiming the teleport. This is provided to the AimVisual for rendering an aim effect.
|
||||
/// Note that the set of points provided here can be different from the points used by the Aim Handler to
|
||||
/// determine the teleport destination. For instance, the aim handler might use a very long line segment
|
||||
/// for an aim laser but would provide a shorter line segment in the AimData representing the line
|
||||
/// from the player to the teleport destination.
|
||||
/// </summary>
|
||||
public class AimData
|
||||
{
|
||||
public AimData()
|
||||
{
|
||||
Points = new List<Vector3>();
|
||||
}
|
||||
|
||||
public RaycastHit TargetHitInfo;
|
||||
public bool TargetValid;
|
||||
public Vector3? Destination;
|
||||
public float Radius;
|
||||
|
||||
public List<Vector3> Points { get; private set; }
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
Points.Clear();
|
||||
TargetValid = false;
|
||||
Destination = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This event is raised when the user begins aiming for a target location for a teleport.
|
||||
/// </summary>
|
||||
public event Action EnterStateAim;
|
||||
|
||||
/// <summary>
|
||||
/// Aim and Target handlers are responsible for populating the AimData with the relevant aim data,
|
||||
/// which is used for a number of purposes within the teleport system.
|
||||
/// </summary>
|
||||
public event Action<AimData> UpdateAimData;
|
||||
|
||||
/// <summary>
|
||||
/// The target handler will call this method when the aim data has been updated and is ready to be
|
||||
/// processed by anything that needs to be aware of any changes. This generally includes a visual
|
||||
/// indicator for the aiming and the active orientation handler.
|
||||
/// </summary>
|
||||
/// <param name="aimData"></param>
|
||||
public void OnUpdateAimData(AimData aimData)
|
||||
{
|
||||
if (UpdateAimData != null)
|
||||
{
|
||||
UpdateAimData(aimData);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This event is raised when the aim state is exited. This is typically used by aim visualizers to
|
||||
/// deactivate any visual effects related to aiming.
|
||||
/// </summary>
|
||||
public event Action ExitStateAim;
|
||||
|
||||
/// <summary>
|
||||
/// This coroutine will be running while the aim state is active. The teleport destination will become active,
|
||||
/// and depending on the target and current intention of the user it might enter the CancelAim state or
|
||||
/// PreTeleport state when it is done.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected IEnumerator AimStateCoroutine()
|
||||
{
|
||||
LogState("AimState: Start");
|
||||
CurrentState = States.Aim;
|
||||
EnableMotion(EnableMovementDuringAim, EnableRotationDuringAim);
|
||||
if (EnterStateAim != null)
|
||||
{
|
||||
EnterStateAim();
|
||||
}
|
||||
|
||||
_teleportDestination.gameObject.SetActive(true);
|
||||
|
||||
// Wait until the user is done aiming. The input system will turn this off when the button that triggered aiming is released.
|
||||
while (CurrentIntention == TeleportIntentions.Aim)
|
||||
{
|
||||
yield return null;
|
||||
}
|
||||
|
||||
LogState("AimState: End. Intention: " + CurrentIntention);
|
||||
if (ExitStateAim != null)
|
||||
{
|
||||
ExitStateAim();
|
||||
}
|
||||
|
||||
// Wait until the next frame to proceed to the next state's coroutine.
|
||||
yield return null;
|
||||
|
||||
// If target is valid, enter pre-teleport otherwise cancel the teleport.
|
||||
LogState("AimState: Switch state. Intention: " + CurrentIntention);
|
||||
if ((CurrentIntention == TeleportIntentions.PreTeleport || CurrentIntention == TeleportIntentions.Teleport) &&
|
||||
_teleportDestination.IsValidDestination)
|
||||
{
|
||||
StartCoroutine(PreTeleportStateCoroutine());
|
||||
}
|
||||
else
|
||||
{
|
||||
StartCoroutine(CancelAimStateCoroutine());
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This event is raised when aiming for a teleport destination is aborted. It can be
|
||||
/// useful for cleaning up effects that may have been triggered when entering the Aim state.
|
||||
/// </summary>
|
||||
public event Action EnterStateCancelAim;
|
||||
|
||||
/// <summary>
|
||||
/// This coroutine will be executed when the aim state is cancelled.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected IEnumerator CancelAimStateCoroutine()
|
||||
{
|
||||
LogState("CancelAimState: Start");
|
||||
CurrentState = States.CancelAim;
|
||||
if (EnterStateCancelAim != null)
|
||||
{
|
||||
EnterStateCancelAim();
|
||||
}
|
||||
|
||||
LogState("CancelAimState: End");
|
||||
|
||||
DeactivateDestination();
|
||||
|
||||
// Wait until the next frame to proceed to the next state's coroutine.
|
||||
yield return null;
|
||||
|
||||
StartCoroutine(ReadyStateCoroutine());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This event is raised when the system enteres the PreTeleport state.
|
||||
/// </summary>
|
||||
public event Action EnterStatePreTeleport;
|
||||
|
||||
/// <summary>
|
||||
/// This coroutine will be active while the system is in the PreTeleport state.
|
||||
/// At this point, the user has indicated they want to teleport however there is a possibility that the
|
||||
/// target they have chosen might be or become invalid so the next state will be either Teleporting or
|
||||
/// CancelTeleporting.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected IEnumerator PreTeleportStateCoroutine()
|
||||
{
|
||||
LogState("PreTeleportState: Start");
|
||||
CurrentState = States.PreTeleport;
|
||||
EnableMotion(EnableMovementDuringPreTeleport, EnableRotationDuringPreTeleport);
|
||||
if (EnterStatePreTeleport != null)
|
||||
{
|
||||
EnterStatePreTeleport();
|
||||
}
|
||||
|
||||
while (CurrentIntention == TeleportIntentions.PreTeleport || IsPreTeleportRequested)
|
||||
{
|
||||
yield return null;
|
||||
}
|
||||
|
||||
LogState("PreTeleportState: End");
|
||||
|
||||
// Most of the state coroutines will wait until the next frame to proceed to the next state's coroutine,
|
||||
// however the PreTeleportState may need to be processed quickly for situations where the teleport needs
|
||||
// to occur on the downpress of a button (AvatarTouch capactive touch for aim and teleport, for instance).
|
||||
|
||||
if (_teleportDestination.IsValidDestination)
|
||||
{
|
||||
StartCoroutine(TeleportingStateCoroutine());
|
||||
}
|
||||
else
|
||||
{
|
||||
StartCoroutine(CancelTeleportStateCoroutine());
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This event will occur if the user cancels the teleport after the destination has been selected.
|
||||
/// Typically not much different than cancelling an aim state, however there may be some effect
|
||||
/// triggered by the target selection which needs to be cleaned up, or perhaps a different visual
|
||||
/// effect needs to be triggered when a teleport is aborted.
|
||||
/// </summary>
|
||||
public event Action EnterStateCancelTeleport;
|
||||
|
||||
/// <summary>
|
||||
/// This coroutine will be executed when the pre-teleport state is unabled to transition to the teleporting state.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected IEnumerator CancelTeleportStateCoroutine()
|
||||
{
|
||||
LogState("CancelTeleportState: Start");
|
||||
CurrentState = States.CancelTeleport;
|
||||
if (EnterStateCancelTeleport != null)
|
||||
{
|
||||
EnterStateCancelTeleport();
|
||||
}
|
||||
|
||||
LogState("CancelTeleportState: End");
|
||||
|
||||
// Teleport was cancelled, notify the teleport destination.
|
||||
DeactivateDestination();
|
||||
|
||||
// Wait until the next frame to proceed to the next state's coroutine.
|
||||
yield return null;
|
||||
|
||||
StartCoroutine(ReadyStateCoroutine());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This event will occur when the teleport actually occurs. There should be one Transition Handler
|
||||
/// enabled and attached to this event. There may be other handlers attached to this event to trigger
|
||||
/// sound effects or gameplay logic to respond to the teleport event.
|
||||
///
|
||||
/// The transition handler is responsible for actually moving the player to the destination, and can achieve
|
||||
/// this goal however it wants. Example teleport transition handlers include:
|
||||
/// * Instant - Just move the player with no delay or effect.
|
||||
/// * Blink - Fade the camera to black, teleport, then fade back up.
|
||||
/// * Warp - Translate the camera over some fixed amount of time to the new destination.
|
||||
/// </summary>
|
||||
public event Action EnterStateTeleporting;
|
||||
|
||||
/// <summary>
|
||||
/// This coroutine will yield until IsTransitioning back to false, which will be immediately unless there
|
||||
/// is a transition handler that needs to take some time to move the player to the new location.
|
||||
/// This allows transition handlers to take as much (or little) time as they need to complete their task
|
||||
/// of moving the player to the teleport destination.
|
||||
/// </summary>
|
||||
protected IEnumerator TeleportingStateCoroutine()
|
||||
{
|
||||
LogState("TeleportingState: Start");
|
||||
CurrentState = States.Teleporting;
|
||||
EnableMotion(false, false); // movement is always disabled during teleport.
|
||||
if (EnterStateTeleporting != null)
|
||||
{
|
||||
EnterStateTeleporting();
|
||||
}
|
||||
|
||||
// If a handler sets this, it needs to clear it when the transition completes.
|
||||
while (IsTransitioning)
|
||||
{
|
||||
yield return null;
|
||||
}
|
||||
|
||||
LogState("TeleportingState: End");
|
||||
|
||||
// Wait until the next frame to proceed to the next state's coroutine.
|
||||
yield return null;
|
||||
|
||||
StartCoroutine(PostTeleportStateCoroutine());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This event will occur after the teleport has completed.
|
||||
/// </summary>
|
||||
public event Action EnterStatePostTeleport;
|
||||
|
||||
/// <summary>
|
||||
/// The PostTeleport coroutine is typically just a single frame state that deactivates the destination
|
||||
/// indicator and raises the EnterStatePostTeleport event which could be used for any number of gameplay
|
||||
/// purposes such as triggering a character animation, sound effect or possibly delaying the exit of the
|
||||
/// PostTeleport state for some gameplay reason such as a cooldown on teleports.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected IEnumerator PostTeleportStateCoroutine()
|
||||
{
|
||||
LogState("PostTeleportState: Start");
|
||||
CurrentState = States.PostTeleport;
|
||||
EnableMotion(EnableMovementDuringPostTeleport, EnableRotationDuringPostTeleport);
|
||||
if (EnterStatePostTeleport != null)
|
||||
{
|
||||
EnterStatePostTeleport();
|
||||
}
|
||||
|
||||
while (IsPostTeleportRequested)
|
||||
{
|
||||
yield return null;
|
||||
}
|
||||
|
||||
LogState("PostTeleportState: End");
|
||||
|
||||
DeactivateDestination();
|
||||
|
||||
// Wait until the next frame to proceed to the next state's coroutine.
|
||||
yield return null;
|
||||
|
||||
StartCoroutine(ReadyStateCoroutine());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This event is raised when the character actually teleports, which is typically triggered by the
|
||||
/// transition handler.
|
||||
///
|
||||
/// The first parameter is the character controller's transform.
|
||||
/// The second and third are the position and rotation, respectively, which the character controller
|
||||
/// will be assigned immediately after the event is raised.
|
||||
/// </summary>
|
||||
public event Action<Transform, Vector3, Quaternion> Teleported;
|
||||
|
||||
/// <summary>
|
||||
/// Perform the actual teleport.
|
||||
/// Note that warp transitions do not call this function and instead moves the game object
|
||||
/// during the transition time time.
|
||||
/// </summary>
|
||||
public void DoTeleport()
|
||||
{
|
||||
var character = LocomotionController.CharacterController;
|
||||
var characterTransform = character.transform;
|
||||
var destTransform = _teleportDestination.OrientationIndicator;
|
||||
|
||||
Vector3 destPosition = destTransform.position;
|
||||
destPosition.y += character.height * 0.5f;
|
||||
Quaternion destRotation = _teleportDestination.LandingRotation; // destTransform.rotation;
|
||||
#if false
|
||||
Quaternion destRotation = destTransform.rotation;
|
||||
|
||||
//Debug.Log("Rots: " + destRotation + " " + destTransform.rotation * Quaternion.Euler(0, -LocomotionController.CameraRig.trackingSpace.localEulerAngles.y, 0));
|
||||
|
||||
destRotation =
|
||||
destRotation * Quaternion.Euler(0, -LocomotionController.CameraRig.trackingSpace.localEulerAngles.y, 0);
|
||||
#endif
|
||||
if (Teleported != null)
|
||||
{
|
||||
Teleported(characterTransform, destPosition, destRotation);
|
||||
}
|
||||
|
||||
characterTransform.position = destPosition;
|
||||
characterTransform.rotation = destRotation;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convenience method for finding the character's position.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public Vector3 GetCharacterPosition()
|
||||
{
|
||||
return LocomotionController.CharacterController.transform.position;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return a quaternion for the Y axis of the HMD's orientation.
|
||||
/// Used by orientation handlers to track the current heading before processing user input to adjust it.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public Quaternion GetHeadRotationY()
|
||||
{
|
||||
Quaternion headRotation = Quaternion.identity;
|
||||
#if UNITY_2019_1_OR_NEWER
|
||||
UnityEngine.XR.InputDevice device = UnityEngine.XR.InputDevices.GetDeviceAtXRNode(UnityEngine.XR.XRNode.Head);
|
||||
if (device.isValid)
|
||||
{
|
||||
device.TryGetFeatureValue(UnityEngine.XR.CommonUsages.deviceRotation, out headRotation);
|
||||
}
|
||||
#elif UNITY_2017_2_OR_NEWER
|
||||
List<UnityEngine.XR.XRNodeState> nodeStates = new List<UnityEngine.XR.XRNodeState>();
|
||||
UnityEngine.XR.InputTracking.GetNodeStates(nodeStates);
|
||||
foreach (UnityEngine.XR.XRNodeState n in nodeStates)
|
||||
{
|
||||
if (n.nodeType == UnityEngine.XR.XRNode.Head)
|
||||
{
|
||||
n.TryGetRotation(out headRotation);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#else
|
||||
headRotation = InputTracking.GetLocalRotation(VRNode.Head);
|
||||
#endif
|
||||
Vector3 euler = headRotation.eulerAngles;
|
||||
euler.x = 0;
|
||||
euler.z = 0;
|
||||
headRotation = Quaternion.Euler(euler);
|
||||
return headRotation;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Warp just the position towards the destination.
|
||||
/// </summary>
|
||||
/// <param name="startPos"></param>
|
||||
/// <param name="positionPercent"></param>
|
||||
public void DoWarp(Vector3 startPos, float positionPercent)
|
||||
{
|
||||
var destTransform = _teleportDestination.OrientationIndicator;
|
||||
Vector3 destPosition = destTransform.position;
|
||||
destPosition.y += LocomotionController.CharacterController.height / 2.0f;
|
||||
|
||||
var character = LocomotionController.CharacterController;
|
||||
var characterTransform = character.transform;
|
||||
|
||||
var lerpPosition = Vector3.Lerp(startPos, destPosition, positionPercent);
|
||||
|
||||
characterTransform.position = lerpPosition;
|
||||
|
||||
//LocomotionController.PlayerController.Teleported = true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dfcbed738e5f16548bc6b4284038f7d2
|
||||
timeCreated: 1497025263
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+96
@@ -0,0 +1,96 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
public class SimpleCapsuleWithStickMovement : MonoBehaviour
|
||||
{
|
||||
public bool EnableLinearMovement = true;
|
||||
public bool EnableRotation = true;
|
||||
public bool HMDRotatesPlayer = true;
|
||||
public bool RotationEitherThumbstick = false;
|
||||
public float RotationAngle = 45.0f;
|
||||
public float Speed = 0.0f;
|
||||
public OVRCameraRig CameraRig;
|
||||
|
||||
private bool ReadyToSnapTurn;
|
||||
private Rigidbody _rigidbody;
|
||||
|
||||
public event Action CameraUpdated;
|
||||
public event Action PreCharacterMove;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
_rigidbody = GetComponent<Rigidbody>();
|
||||
if (CameraRig == null) CameraRig = GetComponentInChildren<OVRCameraRig>();
|
||||
}
|
||||
|
||||
void Start()
|
||||
{
|
||||
}
|
||||
|
||||
private void FixedUpdate()
|
||||
{
|
||||
if (CameraUpdated != null) CameraUpdated();
|
||||
if (PreCharacterMove != null) PreCharacterMove();
|
||||
|
||||
if (HMDRotatesPlayer) RotatePlayerToHMD();
|
||||
if (EnableLinearMovement) StickMovement();
|
||||
if (EnableRotation) SnapTurn();
|
||||
}
|
||||
|
||||
void RotatePlayerToHMD()
|
||||
{
|
||||
Transform root = CameraRig.trackingSpace;
|
||||
Transform centerEye = CameraRig.centerEyeAnchor;
|
||||
|
||||
Vector3 prevPos = root.position;
|
||||
Quaternion prevRot = root.rotation;
|
||||
|
||||
transform.rotation = Quaternion.Euler(0.0f, centerEye.rotation.eulerAngles.y, 0.0f);
|
||||
|
||||
root.position = prevPos;
|
||||
root.rotation = prevRot;
|
||||
}
|
||||
|
||||
void StickMovement()
|
||||
{
|
||||
Quaternion ort = CameraRig.centerEyeAnchor.rotation;
|
||||
Vector3 ortEuler = ort.eulerAngles;
|
||||
ortEuler.z = ortEuler.x = 0f;
|
||||
ort = Quaternion.Euler(ortEuler);
|
||||
|
||||
Vector3 moveDir = Vector3.zero;
|
||||
Vector2 primaryAxis = OVRInput.Get(OVRInput.Axis2D.PrimaryThumbstick);
|
||||
moveDir += ort * (primaryAxis.x * Vector3.right);
|
||||
moveDir += ort * (primaryAxis.y * Vector3.forward);
|
||||
//_rigidbody.MovePosition(_rigidbody.transform.position + moveDir * Speed * Time.fixedDeltaTime);
|
||||
_rigidbody.MovePosition(_rigidbody.position + moveDir * Speed * Time.fixedDeltaTime);
|
||||
}
|
||||
|
||||
void SnapTurn()
|
||||
{
|
||||
if (OVRInput.Get(OVRInput.Button.SecondaryThumbstickLeft) ||
|
||||
(RotationEitherThumbstick && OVRInput.Get(OVRInput.Button.PrimaryThumbstickLeft)))
|
||||
{
|
||||
if (ReadyToSnapTurn)
|
||||
{
|
||||
ReadyToSnapTurn = false;
|
||||
transform.RotateAround(CameraRig.centerEyeAnchor.position, Vector3.up, -RotationAngle);
|
||||
}
|
||||
}
|
||||
else if (OVRInput.Get(OVRInput.Button.SecondaryThumbstickRight) ||
|
||||
(RotationEitherThumbstick && OVRInput.Get(OVRInput.Button.PrimaryThumbstickRight)))
|
||||
{
|
||||
if (ReadyToSnapTurn)
|
||||
{
|
||||
ReadyToSnapTurn = false;
|
||||
transform.RotateAround(CameraRig.centerEyeAnchor.position, Vector3.up, RotationAngle);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ReadyToSnapTurn = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 847d8b0d968d4a14c89d7508f54c0db7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,54 @@
|
||||
/************************************************************************************
|
||||
|
||||
See SampleFramework license.txt for license terms. Unless required by applicable law
|
||||
or agreed to in writing, the sample code is provided "AS IS" WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied. See the license for specific
|
||||
language governing permissions and limitations under the license.
|
||||
|
||||
************************************************************************************/
|
||||
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
/// <summary>
|
||||
/// TeleportAimHandler will provide a series of points in the world that represent the series of line
|
||||
/// segments (as few as one for a laser) which the player uses to determine where they are aiming for a teleport.
|
||||
/// This is not the visualization of the aiming, it is merely the set of points representing the line, arc, or whatever
|
||||
/// shape makes sense for the teleport aiming mechanism which is then used to perform collision detection with the world
|
||||
/// in order to determine the final teleport target location.
|
||||
/// </summary>
|
||||
public abstract class TeleportAimHandler : TeleportSupport
|
||||
{
|
||||
/// <summary>
|
||||
/// The LocomotionTeleport supports one aim handler at a time. Call the base OnEnable to make sure LocomotionTeleport
|
||||
/// is valid, then assign the current aim handler to this object.
|
||||
/// </summary>
|
||||
protected override void OnEnable()
|
||||
{
|
||||
base.OnEnable();
|
||||
LocomotionTeleport.AimHandler = this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// When this component is disabled, make sure to clear the LocomotionTeleport's aim handler but only if this is
|
||||
/// still the active handler. It's an unlikely edge case but it's more robust to make sure a different aim handler
|
||||
/// wasn't enabled before this was disabled.
|
||||
/// </summary>
|
||||
protected override void OnDisable()
|
||||
{
|
||||
if (LocomotionTeleport.AimHandler == this)
|
||||
{
|
||||
LocomotionTeleport.AimHandler = null;
|
||||
}
|
||||
|
||||
base.OnDisable();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// GetPoints provides the core purpose of this class: Return a sequence of points that represents the line segment
|
||||
/// or segments that should be collision tested against the world.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public abstract void GetPoints(List<Vector3> points);
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 05141a0b7df32dd4e914f070c2c43fdd
|
||||
timeCreated: 1496939485
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,33 @@
|
||||
/************************************************************************************
|
||||
|
||||
See SampleFramework license.txt for license terms. Unless required by applicable law
|
||||
or agreed to in writing, the sample code is provided "AS IS" WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied. See the license for specific
|
||||
language governing permissions and limitations under the license.
|
||||
|
||||
************************************************************************************/
|
||||
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
public class TeleportAimHandlerLaser : TeleportAimHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// Maximum range for aiming.
|
||||
/// </summary>
|
||||
[Tooltip("Maximum range for aiming.")]
|
||||
public float Range = 100;
|
||||
|
||||
/// <summary>
|
||||
/// Return the set of points that represent the aiming line.
|
||||
/// </summary>
|
||||
/// <param name="points"></param>
|
||||
public override void GetPoints(List<Vector3> points)
|
||||
{
|
||||
Ray aimRay;
|
||||
LocomotionTeleport.InputHandler.GetAimData(out aimRay);
|
||||
points.Add(aimRay.origin);
|
||||
points.Add(aimRay.origin + aimRay.direction * Range);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 70bc4ab8bfd254f42902a4d602fef956
|
||||
timeCreated: 1496861328
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,76 @@
|
||||
/************************************************************************************
|
||||
|
||||
See SampleFramework license.txt for license terms. Unless required by applicable law
|
||||
or agreed to in writing, the sample code is provided "AS IS" WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied. See the license for specific
|
||||
language governing permissions and limitations under the license.
|
||||
|
||||
************************************************************************************/
|
||||
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
/// <summary>
|
||||
/// This aim handler simulates the parabolic curve that a thrown item would follow, a common style of teleport aiming.
|
||||
/// </summary>
|
||||
public class TeleportAimHandlerParabolic : TeleportAimHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// Maximum range for aiming.
|
||||
/// </summary>
|
||||
[Tooltip("Maximum range for aiming.")]
|
||||
public float Range;
|
||||
|
||||
/// <summary>
|
||||
/// The MinimumElevation is relative to the AimPosition.
|
||||
/// </summary>
|
||||
[Tooltip("The MinimumElevation is relative to the AimPosition.")]
|
||||
public float MinimumElevation = -100;
|
||||
|
||||
/// <summary>
|
||||
/// The Gravity is used in conjunction with AimVelocity and the aim direction to simulate a projectile.
|
||||
/// </summary>
|
||||
[Tooltip("The Gravity is used in conjunction with AimVelocity and the aim direction to simulate a projectile.")]
|
||||
public float Gravity = -9.8f;
|
||||
|
||||
/// <summary>
|
||||
/// The AimVelocity is the initial speed of the faked projectile.
|
||||
/// </summary>
|
||||
[Tooltip("The AimVelocity is the initial speed of the faked projectile.")]
|
||||
[Range(0.001f, 50.0f)]
|
||||
public float AimVelocity = 1;
|
||||
|
||||
/// <summary>
|
||||
/// The AimStep is the how much to subdivide the iteration.
|
||||
/// </summary>
|
||||
[Tooltip("The AimStep is the how much to subdivide the iteration.")]
|
||||
[Range(0.001f, 1.0f)]
|
||||
public float AimStep = 1;
|
||||
|
||||
/// <summary>
|
||||
/// Return the set of points that represent the aiming line.
|
||||
/// </summary>
|
||||
/// <param name="points"></param>
|
||||
public override void GetPoints(List<Vector3> points)
|
||||
{
|
||||
Ray startRay;
|
||||
|
||||
LocomotionTeleport.InputHandler.GetAimData(out startRay);
|
||||
|
||||
var aimPosition = startRay.origin;
|
||||
var aimDirection = startRay.direction * AimVelocity;
|
||||
var rangeSquared = Range * Range;
|
||||
do
|
||||
{
|
||||
points.Add(aimPosition);
|
||||
|
||||
var aimVector = aimDirection;
|
||||
aimVector.y = aimVector.y + Gravity * 0.0111111111f * AimStep;
|
||||
aimDirection = aimVector;
|
||||
aimPosition += aimVector * AimStep;
|
||||
} while ((aimPosition.y - startRay.origin.y > MinimumElevation) &&
|
||||
((startRay.origin - aimPosition).sqrMagnitude <= rangeSquared));
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f2207d0346672d340874d20d6a45eb69
|
||||
timeCreated: 1496861341
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,87 @@
|
||||
/************************************************************************************
|
||||
|
||||
See SampleFramework license.txt for license terms. Unless required by applicable law
|
||||
or agreed to in writing, the sample code is provided "AS IS" WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied. See the license for specific
|
||||
language governing permissions and limitations under the license.
|
||||
|
||||
************************************************************************************/
|
||||
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
public class TeleportAimVisualLaser : TeleportSupport
|
||||
{
|
||||
/// <summary>
|
||||
/// This prefab will be instantiated when the aim visual is awakened, and will be set active when the
|
||||
/// user is aiming, and deactivated when they are done aiming.
|
||||
/// </summary>
|
||||
[Tooltip(
|
||||
"This prefab will be instantiated when the aim visual is awakened, and will be set active when the " +
|
||||
"user is aiming, and deactivated when they are done aiming.")]
|
||||
public LineRenderer LaserPrefab;
|
||||
|
||||
private readonly Action _enterAimStateAction;
|
||||
private readonly Action _exitAimStateAction;
|
||||
private readonly Action<LocomotionTeleport.AimData> _updateAimDataAction;
|
||||
private LineRenderer _lineRenderer;
|
||||
private Vector3[] _linePoints;
|
||||
|
||||
public TeleportAimVisualLaser()
|
||||
{
|
||||
_enterAimStateAction = EnterAimState;
|
||||
_exitAimStateAction = ExitAimState;
|
||||
_updateAimDataAction = UpdateAimData;
|
||||
}
|
||||
|
||||
private void EnterAimState()
|
||||
{
|
||||
_lineRenderer.gameObject.SetActive(true);
|
||||
}
|
||||
|
||||
private void ExitAimState()
|
||||
{
|
||||
_lineRenderer.gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
void Awake()
|
||||
{
|
||||
LaserPrefab.gameObject.SetActive(false);
|
||||
_lineRenderer = Instantiate(LaserPrefab);
|
||||
}
|
||||
|
||||
protected override void AddEventHandlers()
|
||||
{
|
||||
base.AddEventHandlers();
|
||||
LocomotionTeleport.EnterStateAim += _enterAimStateAction;
|
||||
LocomotionTeleport.ExitStateAim += _exitAimStateAction;
|
||||
LocomotionTeleport.UpdateAimData += _updateAimDataAction;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Derived classes that need to use event handlers need to override this method and
|
||||
/// call the base class to ensure all event handlers are removed as intended.
|
||||
/// </summary>
|
||||
protected override void RemoveEventHandlers()
|
||||
{
|
||||
LocomotionTeleport.EnterStateAim -= _enterAimStateAction;
|
||||
LocomotionTeleport.ExitStateAim -= _exitAimStateAction;
|
||||
LocomotionTeleport.UpdateAimData -= _updateAimDataAction;
|
||||
base.RemoveEventHandlers();
|
||||
}
|
||||
|
||||
private void UpdateAimData(LocomotionTeleport.AimData obj)
|
||||
{
|
||||
_lineRenderer.sharedMaterial.color = obj.TargetValid ? Color.green : Color.red;
|
||||
|
||||
var points = obj.Points;
|
||||
// Debug.Log("AimVisualLaser: count: " + points.Count);
|
||||
_lineRenderer.positionCount = points.Count;
|
||||
//_lineRenderer.SetVertexCount(points.Count);
|
||||
for (int i = 0; i < points.Count; i++)
|
||||
{
|
||||
_lineRenderer.SetPosition(i, points[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: aa8ac578d8d4eff4eae43b9c3eb1529c
|
||||
timeCreated: 1496861392
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,178 @@
|
||||
/************************************************************************************
|
||||
|
||||
See SampleFramework license.txt for license terms. Unless required by applicable law
|
||||
or agreed to in writing, the sample code is provided "AS IS" WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied. See the license for specific
|
||||
language governing permissions and limitations under the license.
|
||||
|
||||
************************************************************************************/
|
||||
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Assertions;
|
||||
|
||||
/// <summary>
|
||||
/// The teleport system uses a prefab with an TeleportDestination component, which will track the target location
|
||||
/// and update a MechAnim to reflect if the destination is valid. Since the user can switch quickly between valid
|
||||
/// targets, it might be possible for a destination to remain active in the scene until a deactivation animation is
|
||||
/// completed. To support this behavior efficiently, these prefabs are managed by a simple object pool.
|
||||
/// Target handlers that don’t rely on discrete locations like Nodes are likely to have only one TeleportDestination
|
||||
/// prefab active at a time, however it is possible that multiple teleports can occur with any target handler type
|
||||
/// and if the TeleportDestination’s MechAnim has a Post Teleport animation it might be necessary to instantiate
|
||||
/// additional OVRTeleportDestinations to allow targeting to occur before the previous destination finishes it’s animation.
|
||||
/// </summary>
|
||||
public class TeleportDestination : MonoBehaviour
|
||||
{
|
||||
/// <summary>
|
||||
/// This can be used by MechAnim to change visuals accordingly.
|
||||
/// </summary>
|
||||
public bool IsValidDestination { get; private set; }
|
||||
|
||||
[Tooltip("If the target handler provides a target position, this transform will be moved to that position " +
|
||||
"and it's game object enabled. A target position being provided does not mean the position is valid, " +
|
||||
"only that the aim handler found something to test as a destination.")]
|
||||
public Transform PositionIndicator;
|
||||
|
||||
[Tooltip("This transform will be rotated to match the rotation of the aiming target. Simple teleport " +
|
||||
"destinations should assign this to the object containing this component. More complex teleport " +
|
||||
"destinations might assign this to a sub-object that is used to indicate the landing orientation " +
|
||||
"independently from the rest of the destination indicator, such as when world space effects are " +
|
||||
"required. This will typically be a child of the PositionIndicator.")]
|
||||
public Transform OrientationIndicator;
|
||||
|
||||
[Tooltip("After the player teleports, the character controller will have it's rotation set to this value. " +
|
||||
"It is different from the OrientationIndicator transform.rotation in order to support both " +
|
||||
"head-relative and forward-facing teleport modes (See TeleportOrientationHandlerThumbstick.cs).")]
|
||||
public Quaternion LandingRotation;
|
||||
|
||||
/// <summary>
|
||||
/// This will be set by the LocomotionTeleport when the object is instantiated.
|
||||
/// </summary>
|
||||
[NonSerialized] public LocomotionTeleport LocomotionTeleport;
|
||||
|
||||
/// <summary>
|
||||
/// The LocomotionTeleport will update this only while this destination is active.
|
||||
/// </summary>
|
||||
[NonSerialized] public LocomotionTeleport.States TeleportState;
|
||||
|
||||
private readonly Action<bool, Vector3?, Quaternion?, Quaternion?> _updateTeleportDestinationAction;
|
||||
private bool _eventsActive;
|
||||
|
||||
TeleportDestination()
|
||||
{
|
||||
_updateTeleportDestinationAction = UpdateTeleportDestination;
|
||||
}
|
||||
|
||||
public void OnEnable()
|
||||
{
|
||||
// Make sure the position and orientation indicators aren't enabled until the destination is updated, otherwise they will flicker at their current location for a frame.
|
||||
PositionIndicator.gameObject.SetActive(false);
|
||||
if (OrientationIndicator != null)
|
||||
{
|
||||
OrientationIndicator.gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
LocomotionTeleport.UpdateTeleportDestination += _updateTeleportDestinationAction;
|
||||
Assert.IsNotNull(OrientationIndicator);
|
||||
_eventsActive = true;
|
||||
}
|
||||
|
||||
void TryDisableEventHandlers()
|
||||
{
|
||||
if (!_eventsActive)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
LocomotionTeleport.UpdateTeleportDestination -= _updateTeleportDestinationAction;
|
||||
_eventsActive = false;
|
||||
}
|
||||
|
||||
public void OnDisable()
|
||||
{
|
||||
TryDisableEventHandlers();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If anything is handling the Deactivated event, then the handlers will be responsible for recycling the object when it is finished.
|
||||
/// </summary>
|
||||
public event Action<TeleportDestination> Deactivated;
|
||||
|
||||
public void OnDeactivated()
|
||||
{
|
||||
if (Deactivated != null)
|
||||
{
|
||||
Deactivated(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
Recycle();
|
||||
}
|
||||
}
|
||||
|
||||
public void Recycle()
|
||||
{
|
||||
LocomotionTeleport.RecycleTeleportDestination(this);
|
||||
}
|
||||
|
||||
public virtual void UpdateTeleportDestination(bool isValidDestination, Vector3? position, Quaternion? rotation,
|
||||
Quaternion? landingRotation)
|
||||
{
|
||||
//Debug.Log("Teleport Destination: "+ position + " " + rotation);
|
||||
|
||||
IsValidDestination = isValidDestination;
|
||||
|
||||
LandingRotation = landingRotation.GetValueOrDefault();
|
||||
|
||||
// Show/hide the position indicator based on there being a valid position for it.
|
||||
var go = PositionIndicator.gameObject;
|
||||
var goActive = go.activeInHierarchy;
|
||||
if (!position.HasValue)
|
||||
{
|
||||
if (goActive)
|
||||
{
|
||||
go.SetActive(false);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!goActive)
|
||||
{
|
||||
go.SetActive(true);
|
||||
}
|
||||
|
||||
transform.position = position.GetValueOrDefault();
|
||||
|
||||
// If there is no orientation indicator specified, rotate the entire indicator to match any provided orientation.
|
||||
if (OrientationIndicator == null)
|
||||
{
|
||||
if (rotation.HasValue)
|
||||
{
|
||||
transform.rotation = rotation.GetValueOrDefault();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Rotate the orientation indicator to match any valid rotation and make it visible,
|
||||
// otherwise hide it.
|
||||
var orientationGO = OrientationIndicator.gameObject;
|
||||
var ogoActive = orientationGO.activeInHierarchy;
|
||||
if (!rotation.HasValue)
|
||||
{
|
||||
if (ogoActive)
|
||||
{
|
||||
orientationGO.SetActive(false);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
OrientationIndicator.rotation = rotation.GetValueOrDefault();
|
||||
if (!ogoActive)
|
||||
{
|
||||
orientationGO.SetActive(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 03a7614f10832d041bccff167d2a460f
|
||||
timeCreated: 1498001764
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,99 @@
|
||||
/************************************************************************************
|
||||
|
||||
See SampleFramework license.txt for license terms. Unless required by applicable law
|
||||
or agreed to in writing, the sample code is provided "AS IS" WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied. See the license for specific
|
||||
language governing permissions and limitations under the license.
|
||||
|
||||
************************************************************************************/
|
||||
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
/// <summary>
|
||||
/// The TeleportInputHandler provides interfaces used to control aim related to teleports and related behaviors.
|
||||
/// There are derived implementations of this for Touch controllers, gamepad and HMD based aiming mechanics.
|
||||
/// Supporting any of these, or other future controllers, is possible by implementing and enabling a different
|
||||
/// derived type of TeleportInputHandler.
|
||||
/// </summary>
|
||||
public abstract class TeleportInputHandler : TeleportSupport
|
||||
{
|
||||
private readonly Action _startReadyAction;
|
||||
private readonly Action _startAimAction;
|
||||
|
||||
protected TeleportInputHandler()
|
||||
{
|
||||
_startReadyAction = () => { StartCoroutine(TeleportReadyCoroutine()); };
|
||||
_startAimAction = () => { StartCoroutine(TeleportAimCoroutine()); };
|
||||
}
|
||||
|
||||
protected override void AddEventHandlers()
|
||||
{
|
||||
LocomotionTeleport.InputHandler = this;
|
||||
base.AddEventHandlers();
|
||||
LocomotionTeleport.EnterStateReady += _startReadyAction;
|
||||
LocomotionTeleport.EnterStateAim += _startAimAction;
|
||||
}
|
||||
|
||||
protected override void RemoveEventHandlers()
|
||||
{
|
||||
if (LocomotionTeleport.InputHandler == this)
|
||||
{
|
||||
LocomotionTeleport.InputHandler = null;
|
||||
}
|
||||
|
||||
LocomotionTeleport.EnterStateReady -= _startReadyAction;
|
||||
LocomotionTeleport.EnterStateAim -= _startAimAction;
|
||||
base.RemoveEventHandlers();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This coroutine will be active while the teleport system is in the Ready state.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
IEnumerator TeleportReadyCoroutine()
|
||||
{
|
||||
while (GetIntention() != LocomotionTeleport.TeleportIntentions.Aim)
|
||||
{
|
||||
yield return null;
|
||||
}
|
||||
|
||||
LocomotionTeleport.CurrentIntention = LocomotionTeleport.TeleportIntentions.Aim;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This coroutine will be active while the teleport system is in the Aim or PreTeleport state.
|
||||
/// It remains active in both the Aim and PreTeleport states because these states are the ones that
|
||||
/// need to switch to different states based on the user intention as detected by the input handler.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
IEnumerator TeleportAimCoroutine()
|
||||
{
|
||||
LocomotionTeleport.TeleportIntentions intention = GetIntention();
|
||||
|
||||
while (intention == LocomotionTeleport.TeleportIntentions.Aim ||
|
||||
intention == LocomotionTeleport.TeleportIntentions.PreTeleport)
|
||||
{
|
||||
LocomotionTeleport.CurrentIntention = intention;
|
||||
yield return null;
|
||||
intention = GetIntention();
|
||||
}
|
||||
|
||||
LocomotionTeleport.CurrentIntention = intention;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// One of the core functions of the TeleportInputHandler is to notify the LocomotionTeleport of the current intentions of the
|
||||
/// user with respect to aiming, teleporting, and abandoning a pending teleport.
|
||||
/// Derivations of this class will check buttons or whatever inputs they require to return values indicating what the user is
|
||||
/// trying to do.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public abstract LocomotionTeleport.TeleportIntentions GetIntention();
|
||||
|
||||
/// <summary>
|
||||
/// Returns the aim ray for pointing at targets, which is generally based on a touch controller or HMD pose.
|
||||
/// </summary>
|
||||
public abstract void GetAimData(out Ray aimRay);
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 687155c0dd8b55d409e36711e0cc7167
|
||||
timeCreated: 1496939263
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,102 @@
|
||||
/************************************************************************************
|
||||
|
||||
See SampleFramework license.txt for license terms. Unless required by applicable law
|
||||
or agreed to in writing, the sample code is provided "AS IS" WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied. See the license for specific
|
||||
language governing permissions and limitations under the license.
|
||||
|
||||
************************************************************************************/
|
||||
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
/// <summary>
|
||||
/// When this component is enabled, the player will be able to aim and trigger teleport behavior using HMD aiming.
|
||||
/// </summary>
|
||||
public class TeleportInputHandlerHMD : TeleportInputHandler
|
||||
{
|
||||
public Transform Pointer { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The button used to begin aiming for a teleport.
|
||||
/// </summary>
|
||||
[Tooltip("The button used to begin aiming for a teleport.")]
|
||||
public OVRInput.RawButton AimButton;
|
||||
|
||||
/// <summary>
|
||||
/// The button used to trigger the teleport after aiming. It can be the same button as the AimButton, however you cannot
|
||||
/// abort a teleport if it is.
|
||||
/// </summary>
|
||||
[Tooltip("The button used to trigger the teleport after aiming. It can be the same button as the AimButton, " +
|
||||
"however you cannot abort a teleport if it is.")]
|
||||
public OVRInput.RawButton TeleportButton;
|
||||
|
||||
/// <summary>
|
||||
/// When true, the system will not use the PreTeleport intention which will allow a teleport to occur on a button downpress.
|
||||
/// When false, the button downpress will trigger the PreTeleport intention and the Teleport intention when the button is released.
|
||||
/// </summary>
|
||||
[Tooltip("When true, the system will not use the PreTeleport intention which will allow a teleport " +
|
||||
"to occur on a button downpress. When false, the button downpress will trigger the PreTeleport " +
|
||||
"intention and the Teleport intention when the button is released.")]
|
||||
public bool FastTeleport;
|
||||
|
||||
/// <summary>
|
||||
/// Based on the input mode, controller state, and current intention of the teleport controller, return the apparent intention of the user.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override LocomotionTeleport.TeleportIntentions GetIntention()
|
||||
{
|
||||
if (!isActiveAndEnabled)
|
||||
{
|
||||
return global::LocomotionTeleport.TeleportIntentions.None;
|
||||
}
|
||||
|
||||
if (LocomotionTeleport.CurrentIntention == global::LocomotionTeleport.TeleportIntentions.Aim)
|
||||
{
|
||||
// If the user has actually pressed the teleport button, enter the preteleport state.
|
||||
if (OVRInput.GetDown(TeleportButton))
|
||||
{
|
||||
return FastTeleport
|
||||
? global::LocomotionTeleport.TeleportIntentions.Teleport
|
||||
: global::LocomotionTeleport.TeleportIntentions.PreTeleport;
|
||||
}
|
||||
}
|
||||
|
||||
// If the user is already in the preteleport state, the intention will be to either remain in this state or switch to Teleport
|
||||
if (LocomotionTeleport.CurrentIntention == global::LocomotionTeleport.TeleportIntentions.PreTeleport)
|
||||
{
|
||||
// If they released the button, switch to Teleport.
|
||||
if (OVRInput.GetUp(TeleportButton))
|
||||
{
|
||||
// Button released, enter the teleport state.
|
||||
return global::LocomotionTeleport.TeleportIntentions.Teleport;
|
||||
}
|
||||
|
||||
// Button still down, remain in PreTeleport so they can orient the destination if an orientation handler supports it.
|
||||
return global::LocomotionTeleport.TeleportIntentions.PreTeleport;
|
||||
}
|
||||
|
||||
|
||||
// Update the aim intention based on the button press state of the AimButton.
|
||||
if (OVRInput.Get(AimButton))
|
||||
{
|
||||
return global::LocomotionTeleport.TeleportIntentions.Aim;
|
||||
}
|
||||
|
||||
// If the aim button is the same as the teleport button, then there is no way to abort the teleport.
|
||||
// Since the process of triggering the teleport is complete, returning the Teleport intention is necessary otherwise
|
||||
// the input handler would remain active.
|
||||
if (AimButton == TeleportButton)
|
||||
{
|
||||
return global::LocomotionTeleport.TeleportIntentions.Teleport;
|
||||
}
|
||||
|
||||
return LocomotionTeleport.TeleportIntentions.None;
|
||||
}
|
||||
|
||||
public override void GetAimData(out Ray aimRay)
|
||||
{
|
||||
var t = LocomotionTeleport.LocomotionController.CameraRig.centerEyeAnchor;
|
||||
aimRay = new Ray(t.position, t.forward);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 810484434e07d83468e261ce07d92106
|
||||
timeCreated: 1491861282
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,286 @@
|
||||
/************************************************************************************
|
||||
|
||||
See SampleFramework license.txt for license terms. Unless required by applicable law
|
||||
or agreed to in writing, the sample code is provided "AS IS" WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied. See the license for specific
|
||||
language governing permissions and limitations under the license.
|
||||
|
||||
************************************************************************************/
|
||||
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
using UnityEngine.Assertions;
|
||||
|
||||
/// <summary>
|
||||
/// When this component is enabled, the player will be able to aim and trigger teleport behavior using Oculus Touch controllers.
|
||||
/// </summary>
|
||||
public class TeleportInputHandlerTouch : TeleportInputHandlerHMD
|
||||
{
|
||||
public Transform LeftHand;
|
||||
public Transform RightHand;
|
||||
|
||||
/// <summary>
|
||||
/// The touch input handler supports three different modes for controlling teleports.
|
||||
/// </summary>
|
||||
public enum InputModes
|
||||
{
|
||||
/// <summary>
|
||||
/// Touching a capacitive button will start the aiming, and pressing that button will trigger the teleport.
|
||||
/// </summary>
|
||||
CapacitiveButtonForAimAndTeleport,
|
||||
|
||||
/// <summary>
|
||||
/// One button will start the aiming, another button will trigger the teleport.
|
||||
/// </summary>
|
||||
SeparateButtonsForAimAndTeleport,
|
||||
|
||||
/// <summary>
|
||||
/// A thumbstick in any direction is used for starting the aiming, and releasing the thumbstick will trigger the teleport.
|
||||
/// </summary>
|
||||
ThumbstickTeleport,
|
||||
|
||||
/// <summary>
|
||||
/// A thumbstick forward or back is used for starting the aiming, and releasing the thumbstick will trigger the teleport.
|
||||
/// </summary>
|
||||
ThumbstickTeleportForwardBackOnly
|
||||
}
|
||||
|
||||
[Tooltip("CapacitiveButtonForAimAndTeleport=Activate aiming via cap touch detection, press the same " +
|
||||
"button to teleport.\nSeparateButtonsForAimAndTeleport=Use one button to begin aiming, and " +
|
||||
"another to trigger the teleport.\nThumbstickTeleport=Push a thumbstick to begin aiming, " +
|
||||
"release to teleport.")]
|
||||
public InputModes InputMode;
|
||||
|
||||
/// <summary>
|
||||
/// These buttons are used for selecting which capacitive button is used when InputMode==CapacitiveButtonForAimAndTeleport
|
||||
/// </summary>
|
||||
public enum AimCapTouchButtons
|
||||
{
|
||||
A,
|
||||
B,
|
||||
LeftTrigger,
|
||||
LeftThumbstick,
|
||||
RightTrigger,
|
||||
RightThumbstick,
|
||||
X,
|
||||
Y
|
||||
}
|
||||
|
||||
private readonly OVRInput.RawButton[] _rawButtons =
|
||||
{
|
||||
OVRInput.RawButton.A,
|
||||
OVRInput.RawButton.B,
|
||||
OVRInput.RawButton.LIndexTrigger,
|
||||
OVRInput.RawButton.LThumbstick,
|
||||
OVRInput.RawButton.RIndexTrigger,
|
||||
OVRInput.RawButton.RThumbstick,
|
||||
OVRInput.RawButton.X,
|
||||
OVRInput.RawButton.Y
|
||||
};
|
||||
|
||||
private readonly OVRInput.RawTouch[] _rawTouch =
|
||||
{
|
||||
OVRInput.RawTouch.A,
|
||||
OVRInput.RawTouch.B,
|
||||
OVRInput.RawTouch.LIndexTrigger,
|
||||
OVRInput.RawTouch.LThumbstick,
|
||||
OVRInput.RawTouch.RIndexTrigger,
|
||||
OVRInput.RawTouch.RThumbstick,
|
||||
OVRInput.RawTouch.X,
|
||||
OVRInput.RawTouch.Y
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Which controller is being used for aiming.
|
||||
/// </summary>
|
||||
[Tooltip("Select the controller to be used for aiming. Supports LTouch, RTouch, or Touch for either.")]
|
||||
public OVRInput.Controller AimingController;
|
||||
|
||||
private OVRInput.Controller InitiatingController;
|
||||
|
||||
/// <summary>
|
||||
/// The button to use for triggering aim and teleport when InputMode==CapacitiveButtonForAimAndTeleport
|
||||
/// </summary>
|
||||
[Tooltip("Select the button to use for triggering aim and teleport when " +
|
||||
"InputMode==CapacitiveButtonForAimAndTeleport")]
|
||||
public AimCapTouchButtons CapacitiveAimAndTeleportButton;
|
||||
|
||||
/// <summary>
|
||||
/// The thumbstick magnitude required to trigger aiming and teleports when InputMode==InputModes.ThumbstickTeleport
|
||||
/// </summary>
|
||||
[Tooltip("The thumbstick magnitude required to trigger aiming and teleports when " +
|
||||
"InputMode==InputModes.ThumbstickTeleport")]
|
||||
public float ThumbstickTeleportThreshold = 0.5f;
|
||||
|
||||
void Start()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Based on the input mode, controller state, and current intention of the teleport controller, return the apparent intention of the user.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override LocomotionTeleport.TeleportIntentions GetIntention()
|
||||
{
|
||||
if (!isActiveAndEnabled)
|
||||
{
|
||||
return global::LocomotionTeleport.TeleportIntentions.None;
|
||||
}
|
||||
|
||||
// If capacitive touch isn't being used, the base implementation will do the work.
|
||||
if (InputMode == InputModes.SeparateButtonsForAimAndTeleport)
|
||||
{
|
||||
return base.GetIntention();
|
||||
}
|
||||
|
||||
// ThumbstickTeleport will begin aiming when the thumbstick is pushed.
|
||||
if (InputMode == InputModes.ThumbstickTeleport || InputMode == InputModes.ThumbstickTeleportForwardBackOnly)
|
||||
{
|
||||
// Note there's a bit of wasted work here if you're only using 1 thumbstick to trigger teleport.
|
||||
// Feel free to delete the extra code for the unnecessary stick.
|
||||
Vector2 leftStick = OVRInput.Get(OVRInput.RawAxis2D.LThumbstick);
|
||||
Vector2 rightStick = OVRInput.Get(OVRInput.RawAxis2D.RThumbstick);
|
||||
float leftMag = 0.0f;
|
||||
float rightMag = 0.0f;
|
||||
float bestMag = 0.0f;
|
||||
OVRInput.Controller bestController = OVRInput.Controller.Touch;
|
||||
bool leftTouched = OVRInput.Get(OVRInput.RawTouch.LThumbstick);
|
||||
bool rightTouched = OVRInput.Get(OVRInput.RawTouch.RThumbstick);
|
||||
|
||||
if (InputMode == InputModes.ThumbstickTeleportForwardBackOnly &&
|
||||
LocomotionTeleport.CurrentIntention != LocomotionTeleport.TeleportIntentions.Aim)
|
||||
{
|
||||
// If user is aiming, ThumbstickTeleport and ThumbstickTeleportForwardBackOnly are identical. But if not, we only want magnitude along the forward or back vector.
|
||||
leftMag = Mathf.Abs(Vector2.Dot(leftStick, Vector2.up));
|
||||
rightMag = Mathf.Abs(Vector2.Dot(rightStick, Vector2.up));
|
||||
}
|
||||
else
|
||||
{
|
||||
leftMag = leftStick.magnitude;
|
||||
rightMag = rightStick.magnitude;
|
||||
}
|
||||
|
||||
if (AimingController == OVRInput.Controller.LTouch)
|
||||
{
|
||||
bestMag = leftMag;
|
||||
bestController = OVRInput.Controller.LTouch;
|
||||
}
|
||||
else if (AimingController == OVRInput.Controller.RTouch)
|
||||
{
|
||||
bestMag = rightMag;
|
||||
bestController = OVRInput.Controller.RTouch;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (leftMag > rightMag)
|
||||
{
|
||||
bestMag = leftMag;
|
||||
bestController = OVRInput.Controller.LTouch;
|
||||
}
|
||||
else
|
||||
{
|
||||
bestMag = rightMag;
|
||||
bestController = OVRInput.Controller.RTouch;
|
||||
}
|
||||
}
|
||||
|
||||
bool touching = bestMag > ThumbstickTeleportThreshold
|
||||
|| (AimingController == OVRInput.Controller.Touch && (leftTouched || rightTouched))
|
||||
|| (AimingController == OVRInput.Controller.LTouch && leftTouched)
|
||||
|| (AimingController == OVRInput.Controller.RTouch && rightTouched);
|
||||
if (!touching)
|
||||
{
|
||||
if (LocomotionTeleport.CurrentIntention == LocomotionTeleport.TeleportIntentions.Aim)
|
||||
{
|
||||
// If the user has released the thumbstick, enter the PreTeleport state unless FastTeleport is enabled,
|
||||
// in which case enter the Teleport state.
|
||||
return FastTeleport
|
||||
? LocomotionTeleport.TeleportIntentions.Teleport
|
||||
: LocomotionTeleport.TeleportIntentions.PreTeleport;
|
||||
}
|
||||
|
||||
// If the user is already in the preteleport state, the intention will be to either remain in this state or switch to Teleport
|
||||
if (LocomotionTeleport.CurrentIntention == LocomotionTeleport.TeleportIntentions.PreTeleport)
|
||||
{
|
||||
return LocomotionTeleport.TeleportIntentions.Teleport;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (LocomotionTeleport.CurrentIntention == LocomotionTeleport.TeleportIntentions.Aim)
|
||||
{
|
||||
return LocomotionTeleport.TeleportIntentions.Aim;
|
||||
}
|
||||
}
|
||||
|
||||
if (bestMag > ThumbstickTeleportThreshold)
|
||||
{
|
||||
InitiatingController = bestController;
|
||||
return LocomotionTeleport.TeleportIntentions.Aim;
|
||||
}
|
||||
|
||||
return LocomotionTeleport.TeleportIntentions.None;
|
||||
}
|
||||
|
||||
// Capacitive touch logic is essentially the same as the base logic, except the button types are different
|
||||
// so different methods need to be used.
|
||||
var teleportButton = _rawButtons[(int)CapacitiveAimAndTeleportButton];
|
||||
|
||||
if (LocomotionTeleport.CurrentIntention == LocomotionTeleport.TeleportIntentions.Aim)
|
||||
{
|
||||
// If the user has actually pressed the teleport button, enter the preteleport state.
|
||||
if (OVRInput.GetDown(teleportButton))
|
||||
{
|
||||
// If the user has released the thumbstick, enter the PreTeleport state unless FastTeleport is enabled,
|
||||
// in which case enter the Teleport state.
|
||||
return FastTeleport
|
||||
? LocomotionTeleport.TeleportIntentions.Teleport
|
||||
: LocomotionTeleport.TeleportIntentions.PreTeleport;
|
||||
}
|
||||
}
|
||||
|
||||
// If the user is already in the PreTeleport state, the intention will be to either remain in this state or switch to Teleport
|
||||
if (LocomotionTeleport.CurrentIntention == LocomotionTeleport.TeleportIntentions.PreTeleport)
|
||||
{
|
||||
// If they released the button, switch to Teleport.
|
||||
if (FastTeleport || OVRInput.GetUp(teleportButton))
|
||||
{
|
||||
// Button released, enter the Teleport state.
|
||||
return LocomotionTeleport.TeleportIntentions.Teleport;
|
||||
}
|
||||
|
||||
// Button still down, remain in PreTeleport so they can orient the destination if an orientation handler supports it.
|
||||
return LocomotionTeleport.TeleportIntentions.PreTeleport;
|
||||
}
|
||||
|
||||
// If it made it this far, then we need to determine if the user intends to be aiming with the capacitive touch.
|
||||
// The first check is if cap touch has been triggered.
|
||||
if (OVRInput.GetDown(_rawTouch[(int)CapacitiveAimAndTeleportButton]))
|
||||
{
|
||||
return LocomotionTeleport.TeleportIntentions.Aim;
|
||||
}
|
||||
|
||||
if (LocomotionTeleport.CurrentIntention == LocomotionTeleport.TeleportIntentions.Aim)
|
||||
{
|
||||
if (!OVRInput.GetUp(_rawTouch[(int)CapacitiveAimAndTeleportButton]))
|
||||
{
|
||||
return LocomotionTeleport.TeleportIntentions.Aim;
|
||||
}
|
||||
}
|
||||
|
||||
return LocomotionTeleport.TeleportIntentions.None;
|
||||
}
|
||||
|
||||
public override void GetAimData(out Ray aimRay)
|
||||
{
|
||||
OVRInput.Controller sourceController = AimingController;
|
||||
if (sourceController == OVRInput.Controller.Touch)
|
||||
{
|
||||
sourceController = InitiatingController;
|
||||
}
|
||||
|
||||
Transform t = (sourceController == OVRInput.Controller.LTouch) ? LeftHand : RightHand;
|
||||
aimRay = new Ray(t.position, t.forward);
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c4133858333ed264ebae0d70265b7b6b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,96 @@
|
||||
/************************************************************************************
|
||||
|
||||
See SampleFramework license.txt for license terms. Unless required by applicable law
|
||||
or agreed to in writing, the sample code is provided "AS IS" WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied. See the license for specific
|
||||
language governing permissions and limitations under the license.
|
||||
|
||||
************************************************************************************/
|
||||
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
/// <summary>
|
||||
/// The orientation handler is what determines the final rotation of the player after the teleport.
|
||||
/// </summary>
|
||||
public abstract class TeleportOrientationHandler : TeleportSupport
|
||||
{
|
||||
private readonly Action _updateOrientationAction;
|
||||
private readonly Action<LocomotionTeleport.AimData> _updateAimDataAction;
|
||||
protected LocomotionTeleport.AimData AimData;
|
||||
|
||||
protected TeleportOrientationHandler()
|
||||
{
|
||||
_updateOrientationAction = () => { StartCoroutine(UpdateOrientationCoroutine()); };
|
||||
_updateAimDataAction = UpdateAimData;
|
||||
}
|
||||
|
||||
private void UpdateAimData(LocomotionTeleport.AimData aimData)
|
||||
{
|
||||
AimData = aimData;
|
||||
}
|
||||
|
||||
protected override void AddEventHandlers()
|
||||
{
|
||||
base.AddEventHandlers();
|
||||
LocomotionTeleport.EnterStateAim += _updateOrientationAction;
|
||||
LocomotionTeleport.UpdateAimData += _updateAimDataAction;
|
||||
}
|
||||
|
||||
protected override void RemoveEventHandlers()
|
||||
{
|
||||
base.RemoveEventHandlers();
|
||||
LocomotionTeleport.EnterStateAim -= _updateOrientationAction;
|
||||
LocomotionTeleport.UpdateAimData -= _updateAimDataAction;
|
||||
}
|
||||
|
||||
private IEnumerator UpdateOrientationCoroutine()
|
||||
{
|
||||
InitializeTeleportDestination();
|
||||
|
||||
while (LocomotionTeleport.CurrentState == LocomotionTeleport.States.Aim ||
|
||||
LocomotionTeleport.CurrentState == LocomotionTeleport.States.PreTeleport)
|
||||
{
|
||||
if (AimData != null)
|
||||
{
|
||||
UpdateTeleportDestination();
|
||||
}
|
||||
|
||||
yield return null;
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void InitializeTeleportDestination();
|
||||
|
||||
protected abstract void UpdateTeleportDestination();
|
||||
|
||||
/// <summary>
|
||||
/// The OrientationModes are used to specify how the character should be oriented when they land
|
||||
/// after a teleport.
|
||||
/// </summary>
|
||||
public enum OrientationModes
|
||||
{
|
||||
/// <summary>
|
||||
/// When the player teleports, they will match the orientation of the destination indicator without adjusting their HMD's
|
||||
/// orientation.
|
||||
/// </summary>
|
||||
HeadRelative,
|
||||
|
||||
/// <summary>
|
||||
/// When the player teleports, the player will be oriented so that when they turn the HMD to match the destination indicator,
|
||||
/// they will be facing forward with respect to the Oculus sensor setup. They will not immediately face the direction of the
|
||||
/// indicator, and will need to rotated the HMD view to match the indicated direction. Once rotated, the player will be facing
|
||||
/// forward to the Oculus sensors.
|
||||
/// </summary>
|
||||
ForwardFacing
|
||||
}
|
||||
|
||||
protected Quaternion GetLandingOrientation(OrientationModes mode, Quaternion rotation)
|
||||
{
|
||||
return mode == OrientationModes.HeadRelative
|
||||
? rotation
|
||||
: rotation * Quaternion.Euler(0,
|
||||
-LocomotionTeleport.LocomotionController.CameraRig.trackingSpace.localEulerAngles.y, 0);
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9e582fd1da19d4b4089aca841af87b66
|
||||
timeCreated: 1496862199
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
/************************************************************************************
|
||||
|
||||
See SampleFramework license.txt for license terms. Unless required by applicable law
|
||||
or agreed to in writing, the sample code is provided "AS IS" WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied. See the license for specific
|
||||
language governing permissions and limitations under the license.
|
||||
|
||||
************************************************************************************/
|
||||
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
/// <summary>
|
||||
/// This orientation handler doesn't actually do anything with the orientation at all; this is for users
|
||||
/// who have a 360 setup and don't need to be concerned with choosing an orientation because they just
|
||||
/// turn whatever direction they want.
|
||||
/// </summary>
|
||||
public class TeleportOrientationHandler360 : TeleportOrientationHandler
|
||||
{
|
||||
protected override void InitializeTeleportDestination()
|
||||
{
|
||||
}
|
||||
|
||||
protected override void UpdateTeleportDestination()
|
||||
{
|
||||
LocomotionTeleport.OnUpdateTeleportDestination(AimData.TargetValid, AimData.Destination, null, null);
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d2051e49b4d4201418c42b0244b2bb47
|
||||
timeCreated: 1496862337
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+101
@@ -0,0 +1,101 @@
|
||||
/************************************************************************************
|
||||
|
||||
See SampleFramework license.txt for license terms. Unless required by applicable law
|
||||
or agreed to in writing, the sample code is provided "AS IS" WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied. See the license for specific
|
||||
language governing permissions and limitations under the license.
|
||||
|
||||
************************************************************************************/
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// This orientation handler will aim the player at the point they aim the HMD at after they choose the teleport location.
|
||||
/// </summary>
|
||||
public class TeleportOrientationHandlerHMD : TeleportOrientationHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// HeadRelative=Character will orient to match the arrow. ForwardFacing=When user orients to match the arrow, they will be facing the sensors.
|
||||
/// </summary>
|
||||
[Tooltip("HeadRelative=Character will orient to match the arrow. ForwardFacing=When user orients to " +
|
||||
"match the arrow, they will be facing the sensors.")]
|
||||
public OrientationModes OrientationMode;
|
||||
|
||||
/// <summary>
|
||||
/// Should the destination orientation be updated during the aim state in addition to the PreTeleport state?
|
||||
/// </summary>
|
||||
[Tooltip("Should the destination orientation be updated during the aim state in addition to " +
|
||||
"the PreTeleport state?")]
|
||||
public bool UpdateOrientationDuringAim;
|
||||
|
||||
/// <summary>
|
||||
/// How far from the destination must the HMD be pointing before using it for orientation
|
||||
/// </summary>
|
||||
[Tooltip("How far from the destination must the HMD be pointing before using it for orientation")]
|
||||
public float AimDistanceThreshold;
|
||||
|
||||
/// <summary>
|
||||
/// How far from the destination must the HMD be pointing before rejecting the teleport
|
||||
/// </summary>
|
||||
[Tooltip("How far from the destination must the HMD be pointing before rejecting the teleport")]
|
||||
public float AimDistanceMaxRange;
|
||||
|
||||
private Quaternion _initialRotation;
|
||||
|
||||
protected override void InitializeTeleportDestination()
|
||||
{
|
||||
_initialRotation = Quaternion.identity;
|
||||
}
|
||||
|
||||
protected override void UpdateTeleportDestination()
|
||||
{
|
||||
// Only update the orientation during preteleport, or if configured to do updates during aim.
|
||||
if (AimData.Destination.HasValue && (UpdateOrientationDuringAim ||
|
||||
LocomotionTeleport.CurrentState == LocomotionTeleport.States.PreTeleport))
|
||||
{
|
||||
var t = LocomotionTeleport.LocomotionController.CameraRig.centerEyeAnchor;
|
||||
var destination = AimData.Destination.GetValueOrDefault();
|
||||
|
||||
// create a plane that contains the destination, with the normal pointing to the HMD.
|
||||
var plane = new Plane(Vector3.up, destination);
|
||||
|
||||
// find the point on the plane that the HMD is looking at.
|
||||
float d;
|
||||
bool hit = plane.Raycast(new Ray(t.position, t.forward), out d);
|
||||
if (hit)
|
||||
{
|
||||
var target = t.position + t.forward * d;
|
||||
var local = target - destination;
|
||||
local.y = 0;
|
||||
var distance = local.magnitude;
|
||||
if (distance > AimDistanceThreshold)
|
||||
{
|
||||
local.Normalize();
|
||||
|
||||
// Some debug draw code to visualize what the math is doing.
|
||||
|
||||
//OVRDebugDraw.AddCross(target, 0.2f, 0.01f, Color.yellow, 0.1f);
|
||||
//OVRDebugDraw.AddCross(destination + new Vector3(local.x, 0, local.z), 0.2f, 0.01f, Color.blue, 0.1f);
|
||||
|
||||
//OVRDebugDraw.AddLine(t.position + new Vector3(0, 0.1f, 0), target, 0.01f, Color.yellow, 1.0f);
|
||||
//OVRDebugDraw.AddLine(target + new Vector3(0, 1f, 0), target - new Vector3(0, 1f, 0), 0.01f, Color.blue, 1.0f);
|
||||
|
||||
var rot = Quaternion.LookRotation(new Vector3(local.x, 0, local.z), Vector3.up);
|
||||
_initialRotation = rot;
|
||||
|
||||
if (AimDistanceMaxRange > 0 && distance > AimDistanceMaxRange)
|
||||
{
|
||||
AimData.TargetValid = false;
|
||||
}
|
||||
|
||||
LocomotionTeleport.OnUpdateTeleportDestination(AimData.TargetValid, AimData.Destination, rot,
|
||||
GetLandingOrientation(OrientationMode, rot));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LocomotionTeleport.OnUpdateTeleportDestination(AimData.TargetValid, AimData.Destination, _initialRotation,
|
||||
GetLandingOrientation(OrientationMode, _initialRotation));
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 40e31156a98eed94e816056346fac4e3
|
||||
timeCreated: 1496862242
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+117
@@ -0,0 +1,117 @@
|
||||
/************************************************************************************
|
||||
|
||||
See SampleFramework license.txt for license terms. Unless required by applicable law
|
||||
or agreed to in writing, the sample code is provided "AS IS" WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied. See the license for specific
|
||||
language governing permissions and limitations under the license.
|
||||
|
||||
************************************************************************************/
|
||||
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
/// <summary>
|
||||
/// This orientation handler will use the specified thumbstick to adjust the landing orientation of the teleport.
|
||||
/// </summary>
|
||||
public class TeleportOrientationHandlerThumbstick : TeleportOrientationHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// HeadRelative=Character will orient to match the arrow. ForwardFacing=When user orients to match the arrow, they will be facing the sensors.
|
||||
/// </summary>
|
||||
[Tooltip(
|
||||
"HeadRelative=Character will orient to match the arrow. ForwardFacing=When user orients to match the arrow, they will be facing the sensors.")]
|
||||
public OrientationModes OrientationMode;
|
||||
|
||||
/// <summary>
|
||||
/// Which thumbstick is to be used for adjusting the teleport orientation.
|
||||
/// </summary>
|
||||
[Tooltip("Which thumbstick is to be used for adjusting the teleport orientation. " +
|
||||
"Supports LTouch, RTouch, or Touch for either.")]
|
||||
public OVRInput.Controller Thumbstick;
|
||||
|
||||
/// <summary>
|
||||
/// The orientation will only change if the thumbstick magnitude is above this value.
|
||||
/// This will usually be larger than the TeleportInputHandlerTouch.ThumbstickTeleportThreshold.
|
||||
/// </summary>
|
||||
[Tooltip("The orientation will only change if the thumbstick magnitude is above this value. " +
|
||||
"This will usually be larger than the TeleportInputHandlerTouch.ThumbstickTeleportThreshold.")]
|
||||
public float RotateStickThreshold = 0.8f;
|
||||
|
||||
private Quaternion _initialRotation;
|
||||
private Quaternion _currentRotation;
|
||||
private Vector2 _lastValidDirection;
|
||||
|
||||
protected override void InitializeTeleportDestination()
|
||||
{
|
||||
_initialRotation = LocomotionTeleport.GetHeadRotationY();
|
||||
_currentRotation = _initialRotation;
|
||||
_lastValidDirection = new Vector2();
|
||||
}
|
||||
|
||||
protected override void UpdateTeleportDestination()
|
||||
{
|
||||
float magnitude;
|
||||
Vector2 direction;
|
||||
if (Thumbstick == OVRInput.Controller.Touch)
|
||||
{
|
||||
Vector2 leftDir = OVRInput.Get(OVRInput.RawAxis2D.LThumbstick);
|
||||
Vector2 rightDir = OVRInput.Get(OVRInput.RawAxis2D.RThumbstick);
|
||||
float leftMag = leftDir.magnitude;
|
||||
float rightMag = rightDir.magnitude;
|
||||
if (leftMag > rightMag)
|
||||
{
|
||||
magnitude = leftMag;
|
||||
direction = leftDir;
|
||||
}
|
||||
else
|
||||
{
|
||||
magnitude = rightMag;
|
||||
direction = rightDir;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Thumbstick == OVRInput.Controller.LTouch) direction = OVRInput.Get(OVRInput.RawAxis2D.LThumbstick);
|
||||
else direction = OVRInput.Get(OVRInput.RawAxis2D.RThumbstick);
|
||||
magnitude = direction.magnitude;
|
||||
}
|
||||
|
||||
if (!AimData.TargetValid)
|
||||
{
|
||||
_lastValidDirection = new Vector2();
|
||||
}
|
||||
|
||||
if (magnitude < RotateStickThreshold)
|
||||
{
|
||||
direction = _lastValidDirection;
|
||||
magnitude = direction.magnitude;
|
||||
|
||||
if (magnitude < RotateStickThreshold)
|
||||
{
|
||||
_initialRotation = LocomotionTeleport.GetHeadRotationY();
|
||||
direction.x = 0;
|
||||
direction.y = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_lastValidDirection = direction;
|
||||
}
|
||||
|
||||
var tracking = LocomotionTeleport.LocomotionController.CameraRig.trackingSpace.rotation;
|
||||
|
||||
if (magnitude > RotateStickThreshold)
|
||||
{
|
||||
direction /= magnitude; // normalize the vector
|
||||
var rot = _initialRotation * Quaternion.LookRotation(new Vector3(direction.x, 0, direction.y), Vector3.up);
|
||||
_currentRotation = tracking * rot;
|
||||
}
|
||||
else
|
||||
{
|
||||
_currentRotation = tracking * LocomotionTeleport.GetHeadRotationY();
|
||||
}
|
||||
|
||||
LocomotionTeleport.OnUpdateTeleportDestination(AimData.TargetValid, AimData.Destination, _currentRotation,
|
||||
GetLandingOrientation(OrientationMode, _currentRotation));
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2bb0f5a590bee8641b2298ad4ad21c1c
|
||||
timeCreated: 1496862269
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Licensed under the Oculus SDK License Agreement (the "License");
|
||||
* you may not use the Oculus SDK except in compliance with the License,
|
||||
* which is provided at the time of installation or download, or which
|
||||
* otherwise accompanies this software in either electronic or hard copy form.
|
||||
*
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://developer.oculus.com/licenses/oculussdk/
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, the Oculus SDK
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
public class TeleportPoint : MonoBehaviour
|
||||
{
|
||||
public float dimmingSpeed = 1;
|
||||
public float fullIntensity = 1;
|
||||
public float lowIntensity = 0.5f;
|
||||
|
||||
public Transform destTransform;
|
||||
|
||||
private float lastLookAtTime = 0;
|
||||
|
||||
|
||||
// Use this for initialization
|
||||
void Start()
|
||||
{
|
||||
}
|
||||
|
||||
public Transform GetDestTransform()
|
||||
{
|
||||
return destTransform;
|
||||
}
|
||||
|
||||
|
||||
// Update is called once per frame
|
||||
void Update()
|
||||
{
|
||||
float intensity = Mathf.SmoothStep(fullIntensity, lowIntensity, (Time.time - lastLookAtTime) * dimmingSpeed);
|
||||
GetComponent<MeshRenderer>().material.SetFloat("_Intensity", intensity);
|
||||
}
|
||||
|
||||
public void OnLookAt()
|
||||
{
|
||||
lastLookAtTime = Time.time;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1787d5d9d5016e24887c57d4163b3ebb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,72 @@
|
||||
/************************************************************************************
|
||||
|
||||
See SampleFramework license.txt for license terms. Unless required by applicable law
|
||||
or agreed to in writing, the sample code is provided "AS IS" WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied. See the license for specific
|
||||
language governing permissions and limitations under the license.
|
||||
|
||||
************************************************************************************/
|
||||
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
/// <summary>
|
||||
/// The TeleportSupport is an EventHandlerBehavior used by a number of derived behaviors
|
||||
/// which all rely on the a LocomotionTeleport component being present and available.
|
||||
/// </summary>
|
||||
public abstract class TeleportSupport : MonoBehaviour
|
||||
{
|
||||
protected LocomotionTeleport LocomotionTeleport { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// This boolean is used to verify that OnEnable/OnDisable virtual functions always call
|
||||
/// the base class implementations to ensure event handlers are attached/detached correctly.
|
||||
/// </summary>
|
||||
private bool _eventsActive;
|
||||
|
||||
/// <summary>
|
||||
/// OnEnable is virtual so that derived classes can set up references to objects before
|
||||
/// AddEventHandlers is called, as is required by TeleportSupport derivations.
|
||||
/// </summary>
|
||||
protected virtual void OnEnable()
|
||||
{
|
||||
LocomotionTeleport = GetComponent<LocomotionTeleport>();
|
||||
Debug.Assert(!_eventsActive);
|
||||
AddEventHandlers();
|
||||
Debug.Assert(_eventsActive);
|
||||
}
|
||||
|
||||
protected virtual void OnDisable()
|
||||
{
|
||||
Debug.Assert(_eventsActive);
|
||||
RemoveEventHandlers();
|
||||
Debug.Assert(!_eventsActive);
|
||||
LocomotionTeleport = null;
|
||||
}
|
||||
|
||||
[System.Diagnostics.Conditional("DEBUG_TELEPORT_EVENT_HANDLERS")]
|
||||
void LogEventHandler(string msg)
|
||||
{
|
||||
Debug.Log("EventHandler: " + GetType().Name + ": " + msg);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Derived classes that need to use event handlers need to override this method and
|
||||
/// call the base class to ensure all event handlers are added as intended.
|
||||
/// </summary>
|
||||
protected virtual void AddEventHandlers()
|
||||
{
|
||||
LogEventHandler("Add");
|
||||
_eventsActive = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Derived classes that need to use event handlers need to override this method and
|
||||
/// call the base class to ensure all event handlers are removed as intended.
|
||||
/// </summary>
|
||||
protected virtual void RemoveEventHandlers()
|
||||
{
|
||||
LogEventHandler("Remove");
|
||||
_eventsActive = false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fe04b5c507a8a0849a67429ae5bb4aa4
|
||||
timeCreated: 1497027819
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,145 @@
|
||||
/************************************************************************************
|
||||
|
||||
See SampleFramework license.txt for license terms. Unless required by applicable law
|
||||
or agreed to in writing, the sample code is provided "AS IS" WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied. See the license for specific
|
||||
language governing permissions and limitations under the license.
|
||||
|
||||
************************************************************************************/
|
||||
|
||||
#define DEBUG_TELEPORT_EVENT_HANDLERS
|
||||
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using Debug = UnityEngine.Debug;
|
||||
|
||||
/// <summary>
|
||||
/// The TeleportTargetHandler's main purpose is to determine when the current aim target is valid
|
||||
/// and to update the teleport destination as required by the design. This allows specialized versions
|
||||
/// that can simply update the destination to any arbitrary location, or update only when a teleport node
|
||||
/// is being pointed at, or anything else that fits the design for limiting when & where a teleport is valid.
|
||||
/// </summary>
|
||||
public abstract class TeleportTargetHandler : TeleportSupport
|
||||
{
|
||||
/// <summary>
|
||||
/// This bitmask controls which game object layers will be included in the targeting collision tests.
|
||||
/// </summary>
|
||||
[Tooltip("This bitmask controls which game object layers will be included in the targeting collision tests.")]
|
||||
public LayerMask AimCollisionLayerMask;
|
||||
|
||||
protected readonly LocomotionTeleport.AimData AimData = new LocomotionTeleport.AimData();
|
||||
private readonly Action _startAimAction;
|
||||
|
||||
protected TeleportTargetHandler()
|
||||
{
|
||||
_startAimAction = () => { StartCoroutine(TargetAimCoroutine()); };
|
||||
}
|
||||
|
||||
protected override void AddEventHandlers()
|
||||
{
|
||||
base.AddEventHandlers();
|
||||
LocomotionTeleport.EnterStateAim += _startAimAction;
|
||||
}
|
||||
|
||||
protected override void RemoveEventHandlers()
|
||||
{
|
||||
base.RemoveEventHandlers();
|
||||
LocomotionTeleport.EnterStateAim -= _startAimAction;
|
||||
}
|
||||
|
||||
private readonly List<Vector3> _aimPoints = new List<Vector3>();
|
||||
|
||||
/// <summary>
|
||||
/// This coroutine is active while the teleport system is in the aiming state.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private IEnumerator TargetAimCoroutine()
|
||||
{
|
||||
// While the teleport system is in the aim state, perform the aim logic and consider teleporting.
|
||||
while (LocomotionTeleport.CurrentState == LocomotionTeleport.States.Aim)
|
||||
{
|
||||
// With each targeting test, we need to reset the AimData to clear the point list and reset flags.
|
||||
ResetAimData();
|
||||
|
||||
// Start the testing with the character's current position to the aiming origin to ensure they
|
||||
// haven't just stuck their hand through something that should have prevented movement.
|
||||
//
|
||||
// The first test won't be added to the aim data results because the visual effects should be from
|
||||
// the aiming origin.
|
||||
|
||||
var current = LocomotionTeleport.transform.position;
|
||||
|
||||
// Enumerate through all the line segments provided by the aim handler, checking for a valid target on each segment,
|
||||
// stopping at the first valid target or when the enumerable runs out of line segments.
|
||||
_aimPoints.Clear();
|
||||
LocomotionTeleport.AimHandler.GetPoints(_aimPoints);
|
||||
|
||||
for (int i = 0; i < _aimPoints.Count; i++)
|
||||
{
|
||||
var adjustedPoint = _aimPoints[i];
|
||||
AimData.TargetValid = ConsiderTeleport(current, ref adjustedPoint);
|
||||
AimData.Points.Add(adjustedPoint);
|
||||
if (AimData.TargetValid)
|
||||
{
|
||||
AimData.Destination = ConsiderDestination(adjustedPoint);
|
||||
AimData.TargetValid = AimData.Destination.HasValue;
|
||||
break;
|
||||
}
|
||||
|
||||
current = _aimPoints[i];
|
||||
}
|
||||
|
||||
LocomotionTeleport.OnUpdateAimData(AimData);
|
||||
yield return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// When a parabolic or other aiming method that consists of many line segments is being used, ConsiderTeleport
|
||||
/// will be called once for each segment so if there is expensive work that can be cached in advance,
|
||||
/// override the ResetAimData method to prepare that data.
|
||||
protected virtual void ResetAimData()
|
||||
{
|
||||
AimData.Reset();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This method will be called while the LocmotionTeleport component is in the aiming state, once for each
|
||||
/// line segment that the targeting beam requires.
|
||||
/// The function should return true whenever an actual target location has been selected.
|
||||
/// </summary>
|
||||
/// <param name="start"></param>
|
||||
/// <param name="end"></param>
|
||||
protected abstract bool ConsiderTeleport(Vector3 start, ref Vector3 end);
|
||||
|
||||
const float ERROR_MARGIN = 0.1f;
|
||||
|
||||
/// <summary>
|
||||
/// Adjust the provided located to account for character height and perform any checks that might
|
||||
/// invalidate the target position of the character controller, such as collision with scene geometry
|
||||
/// or other actors.
|
||||
/// </summary>
|
||||
/// <param name="location"></param>
|
||||
/// <returns></returns>
|
||||
public virtual Vector3? ConsiderDestination(Vector3 location)
|
||||
{
|
||||
var character = LocomotionTeleport.LocomotionController.CharacterController;
|
||||
var radius = character.radius - ERROR_MARGIN;
|
||||
|
||||
var start = location;
|
||||
start.y += radius + ERROR_MARGIN;
|
||||
var end = start;
|
||||
end.y += character.height - ERROR_MARGIN;
|
||||
|
||||
var result = Physics.CheckCapsule(start, end, radius,
|
||||
AimCollisionLayerMask, QueryTriggerInteraction.Ignore);
|
||||
if (result)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return location;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0c41ab9d9362d514f8fb3ab4cb49a809
|
||||
timeCreated: 1496861986
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,98 @@
|
||||
/************************************************************************************
|
||||
|
||||
See SampleFramework license.txt for license terms. Unless required by applicable law
|
||||
or agreed to in writing, the sample code is provided "AS IS" WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied. See the license for specific
|
||||
language governing permissions and limitations under the license.
|
||||
|
||||
************************************************************************************/
|
||||
|
||||
// Enable this define to visualize the navigation solution that was used to validate access to the target location.
|
||||
//#define SHOW_PATH_RESULT
|
||||
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
using System.Diagnostics;
|
||||
|
||||
public class TeleportTargetHandlerNavMesh : TeleportTargetHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// Controls which areas are to be used when doing nav mesh queries.
|
||||
/// </summary>
|
||||
public int NavMeshAreaMask = UnityEngine.AI.NavMesh.AllAreas;
|
||||
|
||||
/// <summary>
|
||||
/// A NavMeshPath that is necessary for doing pathing queries and is reused with each request.
|
||||
/// </summary>
|
||||
private UnityEngine.AI.NavMeshPath _path;
|
||||
|
||||
void Awake()
|
||||
{
|
||||
_path = new UnityEngine.AI.NavMeshPath();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This method will be called while the LocmotionTeleport component is in the aiming state, once for each
|
||||
/// line segment that the targeting beam requires.
|
||||
/// The function should return true whenever an actual target location has been selected.
|
||||
/// </summary>
|
||||
/// <param name="start"></param>
|
||||
/// <param name="end"></param>
|
||||
protected override bool ConsiderTeleport(Vector3 start, ref Vector3 end)
|
||||
{
|
||||
// If the ray hits the world, consider it valid and update the aimRay to the end point.
|
||||
if (LocomotionTeleport.AimCollisionTest(start, end, AimCollisionLayerMask, out AimData.TargetHitInfo))
|
||||
{
|
||||
var d = (end - start).normalized;
|
||||
|
||||
end = start + d * AimData.TargetHitInfo.distance;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This version of ConsiderDestination will only return a valid location if the pathing system is able to find a route
|
||||
/// from the current position to the candidate location.
|
||||
/// </summary>
|
||||
/// <param name="location"></param>
|
||||
/// <returns></returns>
|
||||
public override Vector3? ConsiderDestination(Vector3 location)
|
||||
{
|
||||
var result = base.ConsiderDestination(location);
|
||||
if (result.HasValue)
|
||||
{
|
||||
Vector3 start = LocomotionTeleport.GetCharacterPosition();
|
||||
Vector3 dest = result.GetValueOrDefault();
|
||||
UnityEngine.AI.NavMesh.CalculatePath(start, dest, NavMeshAreaMask, _path);
|
||||
|
||||
if (_path.status == UnityEngine.AI.NavMeshPathStatus.PathComplete)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
[Conditional("SHOW_PATH_RESULT")]
|
||||
private void OnDrawGizmos()
|
||||
{
|
||||
#if SHOW_PATH_RESULT
|
||||
if (_path == null)
|
||||
return;
|
||||
|
||||
var corners = _path.corners;
|
||||
if (corners == null || corners.Length == 0)
|
||||
return;
|
||||
var p = corners[0];
|
||||
for(int i = 1; i < corners.Length; i++)
|
||||
{
|
||||
var p2 = corners[i];
|
||||
Gizmos.DrawLine(p, p2);
|
||||
p = p2;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 246f3f7eae8a20948859c718121d1c69
|
||||
timeCreated: 1496862053
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,67 @@
|
||||
/************************************************************************************
|
||||
|
||||
See SampleFramework license.txt for license terms. Unless required by applicable law
|
||||
or agreed to in writing, the sample code is provided "AS IS" WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied. See the license for specific
|
||||
language governing permissions and limitations under the license.
|
||||
|
||||
************************************************************************************/
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// This target handler will only return locations that the aim system detects that contain a TeleportPoint component.
|
||||
/// </summary>
|
||||
public class TeleportTargetHandlerNode : TeleportTargetHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// When checking line of sight to the destination, add this value to the vertical offset for
|
||||
/// targeting collision checks.
|
||||
/// </summary>
|
||||
[Tooltip("When checking line of sight to the destination, add this value to the vertical offset for " +
|
||||
"targeting collision checks.")]
|
||||
public float LOSOffset = 1.0f;
|
||||
|
||||
/// <summary>
|
||||
/// Teleport logic will only work with TeleportPoint components that exist in the layers
|
||||
/// specified by this mask.
|
||||
/// </summary>
|
||||
[Tooltip("Teleport logic will only work with TeleportPoint components that exist in the layers " +
|
||||
"specified by this mask.")]
|
||||
public LayerMask TeleportLayerMask;
|
||||
|
||||
/// <summary>
|
||||
/// This method will be called while the LocmotionTeleport component is in the aiming state, once for each
|
||||
/// line segment that the targeting beam requires.
|
||||
/// The function should return true whenever an actual target location has been selected.
|
||||
/// </summary>
|
||||
protected override bool ConsiderTeleport(Vector3 start, ref Vector3 end)
|
||||
{
|
||||
// If the ray hits the world, consider it valid and update the aimRay to the end point.
|
||||
if (!LocomotionTeleport.AimCollisionTest(start, end, AimCollisionLayerMask | TeleportLayerMask,
|
||||
out AimData.TargetHitInfo))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
TeleportPoint tp = AimData.TargetHitInfo.collider.gameObject.GetComponent<TeleportPoint>();
|
||||
if (tp == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// The targeting test discovered a valid teleport node. Now test to make sure there is line of sight to the
|
||||
// actual destination. Since the teleport destination is expected to be right on the ground, use the LOSOffset
|
||||
// to bump the collision check up off the ground a bit.
|
||||
var dest = tp.destTransform.position;
|
||||
var offsetEnd = new Vector3(dest.x, dest.y + LOSOffset, dest.z);
|
||||
if (LocomotionTeleport.AimCollisionTest(start, offsetEnd, AimCollisionLayerMask & ~TeleportLayerMask,
|
||||
out AimData.TargetHitInfo))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
end = dest;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3c742df914335504e97e68335f9f7ea6
|
||||
timeCreated: 1496862013
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
/************************************************************************************
|
||||
|
||||
See SampleFramework license.txt for license terms. Unless required by applicable law
|
||||
or agreed to in writing, the sample code is provided "AS IS" WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied. See the license for specific
|
||||
language governing permissions and limitations under the license.
|
||||
|
||||
************************************************************************************/
|
||||
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
using UnityEngine.EventSystems;
|
||||
|
||||
/// <summary>
|
||||
/// This target handler simply returns any location that is detected by the aim collision tests.
|
||||
/// Essentially, any space the player will fit will be a valid teleport destination.
|
||||
/// </summary>
|
||||
public class TeleportTargetHandlerPhysical : TeleportTargetHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// This method will be called while the LocmotionTeleport component is in the aiming state, once for each
|
||||
/// line segment that the targeting beam requires.
|
||||
/// The function should return true whenever an actual target location has been selected.
|
||||
/// </summary>
|
||||
/// <param name="start"></param>
|
||||
/// <param name="end"></param>
|
||||
protected override bool ConsiderTeleport(Vector3 start, ref Vector3 end)
|
||||
{
|
||||
// If the ray hits the world, consider it valid and update the aimRay to the end point.
|
||||
if (LocomotionTeleport.AimCollisionTest(start, end, AimCollisionLayerMask, out AimData.TargetHitInfo))
|
||||
{
|
||||
var d = (end - start).normalized;
|
||||
|
||||
end = start + d * AimData.TargetHitInfo.distance;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7d8fa3b51be1cb745a66b9f32a13f550
|
||||
timeCreated: 1496862037
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,41 @@
|
||||
/************************************************************************************
|
||||
|
||||
See SampleFramework license.txt for license terms. Unless required by applicable law
|
||||
or agreed to in writing, the sample code is provided "AS IS" WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied. See the license for specific
|
||||
language governing permissions and limitations under the license.
|
||||
|
||||
************************************************************************************/
|
||||
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
/// <summary>
|
||||
/// Teleport transitions manage the actual relocation of the player from the current position and orientation
|
||||
/// to the teleport destination.
|
||||
/// All teleport transition behaviors derive from this class, primarily for type safety
|
||||
/// within the LocomotionTeleport to track the current transition type.
|
||||
/// </summary>
|
||||
public abstract class TeleportTransition : TeleportSupport
|
||||
{
|
||||
protected override void AddEventHandlers()
|
||||
{
|
||||
LocomotionTeleport.EnterStateTeleporting += LocomotionTeleportOnEnterStateTeleporting;
|
||||
base.AddEventHandlers();
|
||||
}
|
||||
|
||||
protected override void RemoveEventHandlers()
|
||||
{
|
||||
LocomotionTeleport.EnterStateTeleporting -= LocomotionTeleportOnEnterStateTeleporting;
|
||||
base.RemoveEventHandlers();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// When the teleport state is entered, simply move the player to the new location
|
||||
/// without any delay or other side effects.
|
||||
/// If the transition is not immediate, the transition handler will need to set the LocomotionTeleport.IsTeleporting
|
||||
/// to true for the duration of the transition, setting it to false when the transition is finished which will
|
||||
/// then allow the teleport state machine to switch to the PostTeleport state.
|
||||
/// </summary>
|
||||
protected abstract void LocomotionTeleportOnEnterStateTeleporting();
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d4cb945184171a54fafc0e150e431a59
|
||||
timeCreated: 1496945385
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,78 @@
|
||||
/************************************************************************************
|
||||
|
||||
See SampleFramework license.txt for license terms. Unless required by applicable law
|
||||
or agreed to in writing, the sample code is provided "AS IS" WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied. See the license for specific
|
||||
language governing permissions and limitations under the license.
|
||||
|
||||
************************************************************************************/
|
||||
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
/// <summary>
|
||||
/// This transition will cause the screen to quickly fade to black, perform the repositioning, and then fade
|
||||
/// the view back to normal.
|
||||
/// </summary>
|
||||
public class TeleportTransitionBlink : TeleportTransition
|
||||
{
|
||||
/// <summary>
|
||||
/// How long the transition takes. Usually this is greater than Teleport Delay.
|
||||
/// </summary>
|
||||
[Tooltip("How long the transition takes. Usually this is greater than Teleport Delay.")]
|
||||
[Range(0.01f, 2.0f)]
|
||||
public float TransitionDuration = 0.5f;
|
||||
|
||||
/// <summary>
|
||||
/// At what percentage of the elapsed transition time does the teleport occur?
|
||||
/// </summary>
|
||||
[Tooltip("At what percentage of the elapsed transition time does the teleport occur?")]
|
||||
[Range(0.0f, 1.0f)]
|
||||
public float TeleportDelay = 0.5f;
|
||||
|
||||
/// <summary>
|
||||
/// Fade to black over the duration of the transition.
|
||||
/// </summary>
|
||||
[Tooltip("Fade to black over the duration of the transition")]
|
||||
public AnimationCurve FadeLevels = new AnimationCurve(new Keyframe[3]
|
||||
{ new Keyframe(0, 0), new Keyframe(0.5f, 1.0f), new Keyframe(1.0f, 0.0f) });
|
||||
|
||||
/// <summary>
|
||||
/// When the teleport state is entered, start a coroutine that will handle the
|
||||
/// actual transition effect.
|
||||
/// </summary>
|
||||
protected override void LocomotionTeleportOnEnterStateTeleporting()
|
||||
{
|
||||
StartCoroutine(BlinkCoroutine());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This coroutine will fade out the view, perform the teleport, and then fade the view
|
||||
/// back in.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected IEnumerator BlinkCoroutine()
|
||||
{
|
||||
LocomotionTeleport.IsTransitioning = true;
|
||||
float elapsedTime = 0;
|
||||
var teleportTime = TransitionDuration * TeleportDelay;
|
||||
var teleported = false;
|
||||
while (elapsedTime < TransitionDuration)
|
||||
{
|
||||
yield return null;
|
||||
elapsedTime += Time.deltaTime;
|
||||
if (!teleported && elapsedTime >= teleportTime)
|
||||
{
|
||||
teleported = true;
|
||||
LocomotionTeleport.DoTeleport();
|
||||
}
|
||||
//float fadeLevel = FadeLevels.Evaluate(elapsedTime / TransitionDuration);
|
||||
//OVRInspector.instance.fader.SetFadeLevel(fadeLevel);
|
||||
}
|
||||
|
||||
//OVRInspector.instance.fader.SetFadeLevel(0);
|
||||
|
||||
LocomotionTeleport.IsTransitioning = false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 65ac96eeca5eff442ba798f7bfc4f002
|
||||
timeCreated: 1496945416
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,26 @@
|
||||
/************************************************************************************
|
||||
|
||||
See SampleFramework license.txt for license terms. Unless required by applicable law
|
||||
or agreed to in writing, the sample code is provided "AS IS" WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied. See the license for specific
|
||||
language governing permissions and limitations under the license.
|
||||
|
||||
************************************************************************************/
|
||||
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
/// <summary>
|
||||
/// This transition will move the player with no other side effects.
|
||||
/// </summary>
|
||||
public class TeleportTransitionInstant : TeleportTransition
|
||||
{
|
||||
/// <summary>
|
||||
/// When the teleport state is entered, simply move the player to the new location
|
||||
/// without any delay or other side effects.
|
||||
/// </summary>
|
||||
protected override void LocomotionTeleportOnEnterStateTeleporting()
|
||||
{
|
||||
LocomotionTeleport.DoTeleport();
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 39fbe3faa8f659944b47b2bb36927a5d
|
||||
timeCreated: 1496945400
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,66 @@
|
||||
/************************************************************************************
|
||||
|
||||
See SampleFramework license.txt for license terms. Unless required by applicable law
|
||||
or agreed to in writing, the sample code is provided "AS IS" WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied. See the license for specific
|
||||
language governing permissions and limitations under the license.
|
||||
|
||||
************************************************************************************/
|
||||
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
/// <summary>
|
||||
/// This transition will move the player to the destination over the span of a fixed amount of time.
|
||||
/// It will not adjust the orientation of the player because this is very uncomfortable.
|
||||
/// Note there is custom editor for this behavior which is used to control the warp interpolation.
|
||||
/// </summary>
|
||||
public class TeleportTransitionWarp : TeleportTransition
|
||||
{
|
||||
/// <summary>
|
||||
/// How much time the warp transition takes to complete.
|
||||
/// </summary>
|
||||
[Tooltip("How much time the warp transition takes to complete.")]
|
||||
[Range(0.01f, 1.0f)]
|
||||
public float TransitionDuration = 0.5f;
|
||||
|
||||
/// <summary>
|
||||
/// Curve to control the position lerp between the current location and the destination.
|
||||
/// There is a custom editor for this field to avoid a problem where inspector curves don't update as expected.
|
||||
/// The custom inspector code is here: .\Editor\OVRTeleportTransitionWarpInspector.cs
|
||||
/// </summary>
|
||||
[HideInInspector]
|
||||
public AnimationCurve PositionLerp = AnimationCurve.Linear(0, 0, 1, 1);
|
||||
|
||||
/// <summary>
|
||||
/// When the teleport state is entered, quickly move the player to the new location
|
||||
/// over the duration of the teleport.
|
||||
/// </summary>
|
||||
protected override void LocomotionTeleportOnEnterStateTeleporting()
|
||||
{
|
||||
StartCoroutine(DoWarp());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This coroutine will be active during the teleport transition and will move the camera
|
||||
/// according to the PositionLerp curve.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
IEnumerator DoWarp()
|
||||
{
|
||||
LocomotionTeleport.IsTransitioning = true;
|
||||
var startPosition = LocomotionTeleport.GetCharacterPosition();
|
||||
float elapsedTime = 0;
|
||||
while (elapsedTime < TransitionDuration)
|
||||
{
|
||||
elapsedTime += Time.deltaTime;
|
||||
var t = elapsedTime / TransitionDuration;
|
||||
var pLerp = PositionLerp.Evaluate(t);
|
||||
LocomotionTeleport.DoWarp(startPosition, pLerp);
|
||||
yield return null;
|
||||
}
|
||||
|
||||
LocomotionTeleport.DoWarp(startPosition, 1.0f);
|
||||
LocomotionTeleport.IsTransitioning = false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b1bbfae4990937048b888479caae4fdc
|
||||
timeCreated: 1496945448
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,200 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!1001 &100100000
|
||||
Prefab:
|
||||
m_ObjectHideFlags: 1
|
||||
serializedVersion: 2
|
||||
m_Modification:
|
||||
m_TransformParent: {fileID: 0}
|
||||
m_Modifications: []
|
||||
m_RemovedComponents: []
|
||||
m_ParentPrefab: {fileID: 0}
|
||||
m_RootGameObject: {fileID: 1000012106565122}
|
||||
m_IsPrefabParent: 1
|
||||
--- !u!1 &1000010963410726
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 1
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 100100000}
|
||||
serializedVersion: 5
|
||||
m_Component:
|
||||
- component: {fileID: 4000013012824352}
|
||||
- component: {fileID: 33000011886826330}
|
||||
- component: {fileID: 23000012145311598}
|
||||
m_Layer: 4
|
||||
m_Name: Orientation
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!1 &1000012106565122
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 100100000}
|
||||
serializedVersion: 5
|
||||
m_Component:
|
||||
- component: {fileID: 4000014291504098}
|
||||
- component: {fileID: 114000013141257940}
|
||||
m_Layer: 4
|
||||
m_Name: TeleportDestination
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 0
|
||||
--- !u!1 &1000014112855926
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 100100000}
|
||||
serializedVersion: 5
|
||||
m_Component:
|
||||
- component: {fileID: 4000011801263008}
|
||||
- component: {fileID: 33000012318126592}
|
||||
- component: {fileID: 23000010924140402}
|
||||
m_Layer: 4
|
||||
m_Name: Position
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!4 &4000011801263008
|
||||
Transform:
|
||||
m_ObjectHideFlags: 1
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 100100000}
|
||||
m_GameObject: {fileID: 1000014112855926}
|
||||
m_LocalRotation: {x: 0, y: -0, z: -0, w: 1}
|
||||
m_LocalPosition: {x: -0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_Children:
|
||||
- {fileID: 4000013012824352}
|
||||
m_Father: {fileID: 4000014291504098}
|
||||
m_RootOrder: 0
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!4 &4000013012824352
|
||||
Transform:
|
||||
m_ObjectHideFlags: 1
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 100100000}
|
||||
m_GameObject: {fileID: 1000010963410726}
|
||||
m_LocalRotation: {x: 0, y: -0, z: -0, w: 1}
|
||||
m_LocalPosition: {x: -0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_Children: []
|
||||
m_Father: {fileID: 4000011801263008}
|
||||
m_RootOrder: 0
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!4 &4000014291504098
|
||||
Transform:
|
||||
m_ObjectHideFlags: 1
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 100100000}
|
||||
m_GameObject: {fileID: 1000012106565122}
|
||||
m_LocalRotation: {x: 0, y: -0, z: -0, w: 1}
|
||||
m_LocalPosition: {x: -0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 100, y: 100, z: 100}
|
||||
m_Children:
|
||||
- {fileID: 4000011801263008}
|
||||
m_Father: {fileID: 0}
|
||||
m_RootOrder: 0
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!23 &23000010924140402
|
||||
MeshRenderer:
|
||||
m_ObjectHideFlags: 1
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 100100000}
|
||||
m_GameObject: {fileID: 1000014112855926}
|
||||
m_Enabled: 1
|
||||
m_CastShadows: 1
|
||||
m_ReceiveShadows: 1
|
||||
m_DynamicOccludee: 1
|
||||
m_MotionVectors: 1
|
||||
m_LightProbeUsage: 1
|
||||
m_ReflectionProbeUsage: 1
|
||||
m_Materials:
|
||||
- {fileID: 2100000, guid: 24774b6e918e3c24a833857353a28b1b, type: 2}
|
||||
m_StaticBatchInfo:
|
||||
firstSubMesh: 0
|
||||
subMeshCount: 0
|
||||
m_StaticBatchRoot: {fileID: 0}
|
||||
m_ProbeAnchor: {fileID: 0}
|
||||
m_LightProbeVolumeOverride: {fileID: 0}
|
||||
m_ScaleInLightmap: 1
|
||||
m_PreserveUVs: 0
|
||||
m_IgnoreNormalsForChartDetection: 0
|
||||
m_ImportantGI: 0
|
||||
m_StitchLightmapSeams: 0
|
||||
m_SelectedEditorRenderState: 3
|
||||
m_MinimumChartSize: 4
|
||||
m_AutoUVMaxDistance: 0.5
|
||||
m_AutoUVMaxAngle: 89
|
||||
m_LightmapParameters: {fileID: 0}
|
||||
m_SortingLayerID: 0
|
||||
m_SortingLayer: 0
|
||||
m_SortingOrder: 0
|
||||
--- !u!23 &23000012145311598
|
||||
MeshRenderer:
|
||||
m_ObjectHideFlags: 1
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 100100000}
|
||||
m_GameObject: {fileID: 1000010963410726}
|
||||
m_Enabled: 1
|
||||
m_CastShadows: 1
|
||||
m_ReceiveShadows: 1
|
||||
m_DynamicOccludee: 1
|
||||
m_MotionVectors: 1
|
||||
m_LightProbeUsage: 1
|
||||
m_ReflectionProbeUsage: 1
|
||||
m_Materials:
|
||||
- {fileID: 2100000, guid: 24774b6e918e3c24a833857353a28b1b, type: 2}
|
||||
m_StaticBatchInfo:
|
||||
firstSubMesh: 0
|
||||
subMeshCount: 0
|
||||
m_StaticBatchRoot: {fileID: 0}
|
||||
m_ProbeAnchor: {fileID: 0}
|
||||
m_LightProbeVolumeOverride: {fileID: 0}
|
||||
m_ScaleInLightmap: 1
|
||||
m_PreserveUVs: 0
|
||||
m_IgnoreNormalsForChartDetection: 0
|
||||
m_ImportantGI: 0
|
||||
m_StitchLightmapSeams: 0
|
||||
m_SelectedEditorRenderState: 3
|
||||
m_MinimumChartSize: 4
|
||||
m_AutoUVMaxDistance: 0.5
|
||||
m_AutoUVMaxAngle: 89
|
||||
m_LightmapParameters: {fileID: 0}
|
||||
m_SortingLayerID: 0
|
||||
m_SortingLayer: 0
|
||||
m_SortingOrder: 0
|
||||
--- !u!33 &33000011886826330
|
||||
MeshFilter:
|
||||
m_ObjectHideFlags: 1
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 100100000}
|
||||
m_GameObject: {fileID: 1000010963410726}
|
||||
m_Mesh: {fileID: 4300002, guid: 823dc0eb5b064e14da00166d21f93fef, type: 3}
|
||||
--- !u!33 &33000012318126592
|
||||
MeshFilter:
|
||||
m_ObjectHideFlags: 1
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 100100000}
|
||||
m_GameObject: {fileID: 1000014112855926}
|
||||
m_Mesh: {fileID: 4300000, guid: 823dc0eb5b064e14da00166d21f93fef, type: 3}
|
||||
--- !u!114 &114000013141257940
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 1
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 100100000}
|
||||
m_GameObject: {fileID: 1000012106565122}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 03a7614f10832d041bccff167d2a460f, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
PositionIndicator: {fileID: 4000011801263008}
|
||||
OrientationIndicator: {fileID: 4000013012824352}
|
||||
LandingRotation: {x: 0, y: 0, z: 0, w: 0}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1b474618c4fc5f54e8a8b803c8352c7d
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,136 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!1001 &100100000
|
||||
Prefab:
|
||||
m_ObjectHideFlags: 1
|
||||
serializedVersion: 2
|
||||
m_Modification:
|
||||
m_TransformParent: {fileID: 0}
|
||||
m_Modifications: []
|
||||
m_RemovedComponents: []
|
||||
m_ParentPrefab: {fileID: 0}
|
||||
m_RootGameObject: {fileID: 1000013999393296}
|
||||
m_IsPrefabParent: 1
|
||||
--- !u!1 &1000013999393296
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 100100000}
|
||||
serializedVersion: 5
|
||||
m_Component:
|
||||
- component: {fileID: 4000010951004030}
|
||||
- component: {fileID: 120000014163304990}
|
||||
m_Layer: 0
|
||||
m_Name: TeleportLaser
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 0
|
||||
--- !u!4 &4000010951004030
|
||||
Transform:
|
||||
m_ObjectHideFlags: 1
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 100100000}
|
||||
m_GameObject: {fileID: 1000013999393296}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_RootOrder: 0
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!120 &120000014163304990
|
||||
LineRenderer:
|
||||
m_ObjectHideFlags: 1
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 100100000}
|
||||
m_GameObject: {fileID: 1000013999393296}
|
||||
m_Enabled: 1
|
||||
m_CastShadows: 0
|
||||
m_ReceiveShadows: 0
|
||||
m_DynamicOccludee: 1
|
||||
m_MotionVectors: 0
|
||||
m_LightProbeUsage: 0
|
||||
m_ReflectionProbeUsage: 0
|
||||
m_Materials:
|
||||
- {fileID: 2100000, guid: a379cec2ba497874788d17eb312c61be, type: 2}
|
||||
m_StaticBatchInfo:
|
||||
firstSubMesh: 0
|
||||
subMeshCount: 0
|
||||
m_StaticBatchRoot: {fileID: 0}
|
||||
m_ProbeAnchor: {fileID: 0}
|
||||
m_LightProbeVolumeOverride: {fileID: 0}
|
||||
m_ScaleInLightmap: 1
|
||||
m_PreserveUVs: 0
|
||||
m_IgnoreNormalsForChartDetection: 0
|
||||
m_ImportantGI: 0
|
||||
m_StitchLightmapSeams: 0
|
||||
m_SelectedEditorRenderState: 3
|
||||
m_MinimumChartSize: 4
|
||||
m_AutoUVMaxDistance: 0.5
|
||||
m_AutoUVMaxAngle: 89
|
||||
m_LightmapParameters: {fileID: 0}
|
||||
m_SortingLayerID: 0
|
||||
m_SortingLayer: 0
|
||||
m_SortingOrder: 0
|
||||
m_Positions:
|
||||
- {x: 0, y: 0, z: 0}
|
||||
- {x: 0, y: 0, z: 1}
|
||||
m_Parameters:
|
||||
serializedVersion: 2
|
||||
widthMultiplier: 1
|
||||
widthCurve:
|
||||
serializedVersion: 2
|
||||
m_Curve:
|
||||
- serializedVersion: 2
|
||||
time: 0
|
||||
value: 0.01
|
||||
inSlope: 0
|
||||
outSlope: 0
|
||||
tangentMode: 0
|
||||
- serializedVersion: 2
|
||||
time: 1
|
||||
value: 0.01
|
||||
inSlope: 0
|
||||
outSlope: 0
|
||||
tangentMode: 0
|
||||
m_PreInfinity: 2
|
||||
m_PostInfinity: 2
|
||||
m_RotationOrder: 4
|
||||
colorGradient:
|
||||
serializedVersion: 2
|
||||
key0: {r: 1, g: 1, b: 1, a: 1}
|
||||
key1: {r: 1, g: 1, b: 1, a: 1}
|
||||
key2: {r: 0, g: 0, b: 0, a: 0}
|
||||
key3: {r: 0, g: 0, b: 0, a: 0}
|
||||
key4: {r: 0, g: 0, b: 0, a: 0}
|
||||
key5: {r: 0, g: 0, b: 0, a: 0}
|
||||
key6: {r: 0, g: 0, b: 0, a: 0}
|
||||
key7: {r: 0, g: 0, b: 0, a: 0}
|
||||
ctime0: 0
|
||||
ctime1: 65535
|
||||
ctime2: 0
|
||||
ctime3: 0
|
||||
ctime4: 0
|
||||
ctime5: 0
|
||||
ctime6: 0
|
||||
ctime7: 0
|
||||
atime0: 0
|
||||
atime1: 65535
|
||||
atime2: 0
|
||||
atime3: 0
|
||||
atime4: 0
|
||||
atime5: 0
|
||||
atime6: 0
|
||||
atime7: 0
|
||||
m_Mode: 0
|
||||
m_NumColorKeys: 2
|
||||
m_NumAlphaKeys: 2
|
||||
numCornerVertices: 0
|
||||
numCapVertices: 0
|
||||
alignment: 0
|
||||
textureMode: 0
|
||||
generateLightingData: 0
|
||||
m_UseWorldSpace: 1
|
||||
m_Loop: 0
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 95b2b00d2fc56fa4c806f2cda99f5f89
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,209 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!1 &120854
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 100100000}
|
||||
serializedVersion: 5
|
||||
m_Component:
|
||||
- component: {fileID: 463128}
|
||||
m_Layer: 4
|
||||
m_Name: DestTransform
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!1 &195790
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 100100000}
|
||||
serializedVersion: 5
|
||||
m_Component:
|
||||
- component: {fileID: 476292}
|
||||
- component: {fileID: 3399168}
|
||||
- component: {fileID: 13671688}
|
||||
- component: {fileID: 2343894}
|
||||
- component: {fileID: 11464152}
|
||||
m_Layer: 4
|
||||
m_Name: TeleportPoint
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!4 &463128
|
||||
Transform:
|
||||
m_ObjectHideFlags: 1
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 100100000}
|
||||
m_GameObject: {fileID: 120854}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_Children: []
|
||||
m_Father: {fileID: 476292}
|
||||
m_RootOrder: 0
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!4 &476292
|
||||
Transform:
|
||||
m_ObjectHideFlags: 1
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 100100000}
|
||||
m_GameObject: {fileID: 195790}
|
||||
m_LocalRotation: {x: 0.00000043626193, y: -0.7859503, z: -0.00000015320406, w: 0.61828977}
|
||||
m_LocalPosition: {x: -22, y: -0, z: 30.2}
|
||||
m_LocalScale: {x: 1, y: 3.6497183, z: 1}
|
||||
m_Children:
|
||||
- {fileID: 463128}
|
||||
- {fileID: 4540077733114076}
|
||||
m_Father: {fileID: 0}
|
||||
m_RootOrder: 0
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!23 &2343894
|
||||
MeshRenderer:
|
||||
m_ObjectHideFlags: 1
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 100100000}
|
||||
m_GameObject: {fileID: 195790}
|
||||
m_Enabled: 1
|
||||
m_CastShadows: 0
|
||||
m_ReceiveShadows: 0
|
||||
m_DynamicOccludee: 1
|
||||
m_MotionVectors: 1
|
||||
m_LightProbeUsage: 0
|
||||
m_ReflectionProbeUsage: 1
|
||||
m_Materials:
|
||||
- {fileID: 2100000, guid: 5e53c7a8c2e563c4c90a8fa620eebc2c, type: 2}
|
||||
m_StaticBatchInfo:
|
||||
firstSubMesh: 0
|
||||
subMeshCount: 0
|
||||
m_StaticBatchRoot: {fileID: 0}
|
||||
m_ProbeAnchor: {fileID: 0}
|
||||
m_LightProbeVolumeOverride: {fileID: 0}
|
||||
m_ScaleInLightmap: 1
|
||||
m_PreserveUVs: 1
|
||||
m_IgnoreNormalsForChartDetection: 0
|
||||
m_ImportantGI: 0
|
||||
m_StitchLightmapSeams: 0
|
||||
m_SelectedEditorRenderState: 3
|
||||
m_MinimumChartSize: 4
|
||||
m_AutoUVMaxDistance: 0.5
|
||||
m_AutoUVMaxAngle: 89
|
||||
m_LightmapParameters: {fileID: 0}
|
||||
m_SortingLayerID: 0
|
||||
m_SortingLayer: 0
|
||||
m_SortingOrder: 0
|
||||
--- !u!33 &3399168
|
||||
MeshFilter:
|
||||
m_ObjectHideFlags: 1
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 100100000}
|
||||
m_GameObject: {fileID: 195790}
|
||||
m_Mesh: {fileID: 10206, guid: 0000000000000000e000000000000000, type: 0}
|
||||
--- !u!114 &11464152
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 1
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 100100000}
|
||||
m_GameObject: {fileID: 195790}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 1787d5d9d5016e24887c57d4163b3ebb, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
dimmingSpeed: 8
|
||||
fullIntensity: 2.4
|
||||
lowIntensity: 0.4
|
||||
destTransform: {fileID: 463128}
|
||||
--- !u!136 &13671688
|
||||
CapsuleCollider:
|
||||
m_ObjectHideFlags: 1
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 100100000}
|
||||
m_GameObject: {fileID: 195790}
|
||||
m_Material: {fileID: 0}
|
||||
m_IsTrigger: 0
|
||||
m_Enabled: 1
|
||||
m_Radius: 0.5
|
||||
m_Height: 2.52
|
||||
m_Direction: 1
|
||||
m_Center: {x: 0, y: 0, z: 0}
|
||||
--- !u!1001 &100100000
|
||||
Prefab:
|
||||
m_ObjectHideFlags: 1
|
||||
serializedVersion: 2
|
||||
m_Modification:
|
||||
m_TransformParent: {fileID: 0}
|
||||
m_Modifications: []
|
||||
m_RemovedComponents: []
|
||||
m_ParentPrefab: {fileID: 0}
|
||||
m_RootGameObject: {fileID: 195790}
|
||||
m_IsPrefabParent: 1
|
||||
--- !u!1 &1596145730556768
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 100100000}
|
||||
serializedVersion: 5
|
||||
m_Component:
|
||||
- component: {fileID: 4540077733114076}
|
||||
- component: {fileID: 108714669993115786}
|
||||
m_Layer: 0
|
||||
m_Name: Point light
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!4 &4540077733114076
|
||||
Transform:
|
||||
m_ObjectHideFlags: 1
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 100100000}
|
||||
m_GameObject: {fileID: 1596145730556768}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: -0, y: 0.5, z: -0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_Children: []
|
||||
m_Father: {fileID: 476292}
|
||||
m_RootOrder: 1
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!108 &108714669993115786
|
||||
Light:
|
||||
m_ObjectHideFlags: 1
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 100100000}
|
||||
m_GameObject: {fileID: 1596145730556768}
|
||||
m_Enabled: 1
|
||||
serializedVersion: 8
|
||||
m_Type: 2
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_Intensity: 2
|
||||
m_Range: 2.5
|
||||
m_SpotAngle: 30
|
||||
m_CookieSize: 10
|
||||
m_Shadows:
|
||||
m_Type: 2
|
||||
m_Resolution: -1
|
||||
m_CustomResolution: -1
|
||||
m_Strength: 1
|
||||
m_Bias: 0.05
|
||||
m_NormalBias: 0.4
|
||||
m_NearPlane: 0.2
|
||||
m_Cookie: {fileID: 0}
|
||||
m_DrawHalo: 0
|
||||
m_Flare: {fileID: 0}
|
||||
m_RenderMode: 0
|
||||
m_CullingMask:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
m_Lightmapping: 2
|
||||
m_AreaSize: {x: 1, y: 1}
|
||||
m_BounceIntensity: 1
|
||||
m_ColorTemperature: 6570
|
||||
m_UseColorTemperature: 0
|
||||
m_ShadowRadius: 0
|
||||
m_ShadowAngle: 0
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ded1d2e0d283d62428212702b4ed5f3f
|
||||
timeCreated: 1446224803
|
||||
licenseType: Store
|
||||
NativeFormatImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user