unity5unity3d 关卡编辑器器视角高度怎么调

后使用快捷导航没有帐号?
只需一步,快速开始
查看: 10083|回复: 7
Unity3D基本操作教程(15分钟)
TA的其他好贴
马上注册,加入CGJOY,让你轻松玩转CGJOY。
才可以下载或查看,没有帐号?
用创建简单漫游
1.& && & 建模中使用的图片、文件、文件夹等以及模型中物体、材质等的名称都不能使用中文或者特殊符号,可以使用英文字母、数字、下划线等
2.& && & 调整Max的单位为米
3.& && & 烘培光影的设置
4.& && & 模型的中的植物效果,第一种是单面片植物,需要设置其轴心为其物体的对称中心;第二种是十字交叉的植物效果;第三种则是到Unity3D编辑器中通过地形编辑器系统添加基本设置
5.& && & Fbx导出插件下载地址:
/adsk/servlet/item?siteID=123112&id=
6.& && & 将Max文件中用到的图片都拷贝到Textures目录下,如
0.jpg (18.2 KB, 下载次数: 299)
23:56 上传
7.& && & 再打开Max文件,导出为FBX文件,使用默认设置,FBX文件也放置在和Max文件相同的目录下,如
1.jpg (32 KB, 下载次数: 292)
23:56 上传
导出的时候,可以将模型简单的分类,如地面、植被、楼房等,也可以将模型分为几个区域,如小区1,小区2,学校等等分开导出
8.& && & 将包含Max文件、Fbx文件和Textures文件夹的文件夹拷贝到Unity3D项目的Assets目录下,如下图中红圈
2.jpg (69.12 KB, 下载次数: 295)
23:56 上传
在下一次用Unity3D编辑器开启本项目的时候,编辑器将自动导入/更新该文件夹中的信息,并生成Materials文件夹,如
3.jpg (178 Bytes, 下载次数: 295)
23:56 上传
4.jpg (29.72 KB, 下载次数: 288)
23:56 上传
9.& && & 启动Unity3D编辑器
10.& &选择刚才拷贝进来的文件中的Fbx文件,如
5.jpg (40.61 KB, 下载次数: 292)
23:56 上传
修改其中的Meshes下的Scale Factor和Generate Colliders,如
6.jpg (39.3 KB, 下载次数: 287)
23:56 上传
点击其他Fbx文件或者单击其他区域将弹出如下的对话框
7.jpg (33.93 KB, 下载次数: 287)
23:56 上传
点击Apply即可,类似的方式设置其他Fbx文件
注意,其中植物/植被类的Fbx文件不需要设置Generate Colliders项
11.& &将Fbx文件直接拖放到Hierarchy区域,如
8.jpg (381 Bytes, 下载次数: 288)
23:56 上传
9.jpg (36.9 KB, 下载次数: 293)
23:56 上传
12.& &点击Hierarchy区域中的对象,同时将鼠标移动三维显示区域,同时点击键f,则该对象自动适配显示到三维区域中心,如
10.jpg (38.36 KB, 下载次数: 293)
23:56 上传
13.& &将全部fbx添加完成后,提高场景亮度如下
11.jpg (43.77 KB, 下载次数: 291)
23:56 上传
单击Ambient Light,如下
12.jpg (40.51 KB, 下载次数: 295)
23:56 上传
13.jpg (42.98 KB, 下载次数: 293)
23:56 上传
即可设置完成
14.& &设置第一人称浏览
删除场景中Main Camera
14.jpg (18.19 KB, 下载次数: 293)
23:56 上传
将Project区域的Standard Assets下的Prefabs下的First Person Controller拖到Hierarchy区域中
15.jpg (51.9 KB, 下载次数: 290)
23:56 上传
点选First Person Controller,调整First Person Controller的位置到场景中合适的位置,并设置其高度为1.37到2.1左右
16.jpg (41.9 KB, 下载次数: 287)
23:56 上传
17.jpg (46.78 KB, 下载次数: 287)
23:56 上传
设置First Person Controller的高度在场景中地面之上
18.jpg (42.03 KB, 下载次数: 283)
23:56 上传
15.& &点击运行,即可测试
19.jpg (37.08 KB, 下载次数: 289)
23:56 上传
修改视角控制键为右键
16.& &打开Project区域中的StandardAssets下的CameraScripts下的MouseLook脚本,在
在& & Quaternion originalR
& && & void Update ()
& && && && &&&if (axes == RotationAxes.MouseXAndY)
& && && && &&&{
& && && && && && && &// Read the mouse input axis
中添加一行代码修改为
& && & Quaternion originalR
& && & void Update ()
& && && && &&&if(Input.GetAxis (&Fire2&)==0)
& && && && &&&if (axes == RotationAxes.MouseXAndY)
& && && && &&&{
& && && && && && && &// Read the mouse input axis
20.jpg (51.62 KB, 下载次数: 291)
23:56 上传
如何取消浏览窗口上的右键菜单
只要设置Unity对象的参数即可禁止右键菜单的显示,如下:
&object id=&UnityObject& classid=&clsid: -DE89-A-D 46C 3A781394&
& & width=&600& height=&450&
codebase=&/download_webplayer/UnityWebPlayer.cab#version=2,0,0,0&&
& & &param name=&src& value=&MyDataFile.unity3d& /&
& & &param name=&disableContextMenu& value=&true& /&
& & &embed id=&UnityEmbed& src=&MyDataFile.unity3d& width=&600& height=&450&
& && &&&type=&application/vnd.unity& pluginspage=&/unity-web-player-2.x&
& && &&&disableContextMenu=&true& /&
&/object&植物效果设置
17.& &对于单面片的植物效果,需要设定其材质为Transparent/VertexLit类型,并为其添加公告板脚本
21.jpg (58.83 KB, 下载次数: 288)
23:56 上传
设置材质类型为Transparent/VertexLit类型,如下
22.jpg (60.02 KB, 下载次数: 294)
23:56 上传
给单面片植物添加公告板脚本的方法是先选择该植物,然后点击菜单component下的scripts下的camera Facing Billboard即可,如下
23.jpg (64.26 KB, 下载次数: 291)
23:56 上传
设置材质类型和添加公告板脚本后,如下
24.jpg (60.96 KB, 下载次数: 292)
23:56 上传
如果没有该脚本组件,可以打开脚本编辑器,拷贝如下代码到脚本中,保存到Assets\Scripts下,命名为CameraFacingBillboard.cs即可
using UnityE
using System.C
public class CameraFacingBillboard : MonoBehaviour
& & public Camera cameraToLookAt;
& && & void Start()
& && && && && &cameraToLookAt = Camera.
& & void Update()
& && &&&Vector3 v = cameraToLookAt.transform.position - transform.
& && &&&v.x = v.z = 0.0f;
& && &&&transform.LookAt(cameraToLookAt.transform.position - v);
18.& &对于十字交叉的植物,需要将其材质设定为Nature/Vegetation Two Pass unlit类型
设置前的效果
25.jpg (45.67 KB, 下载次数: 290)
23:56 上传
设置后的效果
26.jpg (46.76 KB, 下载次数: 293)
23:56 上传
水面效果的设置
19.& &创建一个网格面片
27.jpg (54.24 KB, 下载次数: 296)
23:56 上传
20.& &给该水面面片设置水材质和水脚本,如
28.jpg (54.77 KB, 下载次数: 289)
23:56 上传
即可烘培光影贴图的处理
21.& &Unity3D光影烘培的要求
U3D的光影贴图使用的是3Dmax中的标准材质的自发光贴图通道来存储光影贴图相关参数,如
29.jpg (70.11 KB, 下载次数: 296)
23:56 上传
22.& &给每个物体都附上贴图,如果是纯色物体,也付给纯色贴图
23.& &打光后,选择要烘培的物体
30.jpg (40.11 KB, 下载次数: 294)
23:56 上传
设置输出路径
31.jpg (53.31 KB, 下载次数: 288)
23:56 上传
添加烘培输出的贴图类型
32.jpg (48.86 KB, 下载次数: 291)
23:56 上传
添加“LightingMap”类型
33.jpg (36.16 KB, 下载次数: 294)
23:56 上传
设置烘培贴图大小和目标贴图位置为“自发光”
34.jpg (54.05 KB, 下载次数: 296)
23:56 上传
设置烘培材质,选择“输出到源”
35.jpg (54.66 KB, 下载次数: 288)
23:56 上传
点击“渲染”即可
24.& &标准材质贴图的烘培光影处理
a)& && && &物体据有标准材质
36.jpg (48.51 KB, 下载次数: 293)
23:56 上传
b)& && &&&烘培渲染后,物体具有两个贴图
37.jpg (71.91 KB, 下载次数: 283)
23:56 上传
c)& && &&&导出Fbx即可
25.& &多重子材质贴图的烘培光影处理
a)& && && &物体据有多重子材质贴图
38.jpg (62.2 KB, 下载次数: 289)
23:56 上传
b)& && &&&渲染烘培后每个子材质都据有两个贴图
39.jpg (71.97 KB, 下载次数: 292)
23:56 上传
c)& && &&&选择该物体,执行“多维材质2标准材质.ms”脚本,将该多维材质物体按其材质数量分解为标准材质的多个物体,新物体的名字以“原多维材质物体名字~其材质名称”命名,如
40.jpg (90.87 KB, 下载次数: 296)
23:56 上传
41.jpg (52 KB, 下载次数: 292)
23:56 上传
点击“开始转换”,则将该物体从多维材质物体按期子材质分解为多个具有标准材质的物体
42.jpg (107.46 KB, 下载次数: 291)
23:56 上传
d)& && &&&将全部的具有多维材质类型的物体分解完成后,即可导出
26.& &多个物体使用同一贴图的烘培光影处理
因为我们在导入fbx文件到Unity3D编辑器中的时候,使用的都是按贴图来生成材质文件,所以多个物体使用同一贴图时会发生错误,修改其中任何一个的材质设置时,其他的使用该贴图的物体都会受到影响,解决的方法便是在Unity3D编辑器中生成一个具有该贴图的新材质,然后重新付给当前物体。
27.& &在U3D编辑器中修改物体的材质类型为光影贴图
设置物体的材质类型为Lightmapped/Diffuse
43.jpg (45.82 KB, 下载次数: 288)
23:56 上传
根据物体的名称将对应的光影贴图拖动到Lightmapp域,其中标准材质物体的光影贴图名称是“其物体名称LightingMap.tga”;从多维材质类型转换过来的物体的光影贴图名称是“其物体名称中~符合前的部分LightingMap.tga”
44.jpg (45.39 KB, 下载次数: 288)
23:56 上传
(注:以上物体光影材质修改过程,已编写为脚本自动处理,直接使用即可,有问题问技术部,使用方法:
将脚本MakeLightmaped.cs添加到Assets\Editor下,然后在Project窗栏中选择需要处理光影材质的物体(可多选)上点击右键,弹出右键菜单中选择MakeLightmaped即可如何制作连续加载的场景漫游
28.& &场景被分解为多个部分,起始场景比较小,启动后,提示继续下载其他场景,下载一个显示一个
Unity3D基本操作教程(15分钟)
45.jpg (435.35 KB, 下载次数: 282)
23:56 上传
46.jpg (68.54 KB, 下载次数: 283)
23:56 上传
47.jpg (462.54 KB, 下载次数: 286)
23:56 上传
48.jpg (72.19 KB, 下载次数: 281)
23:56 上传
49.jpg (215.33 KB, 下载次数: 282)
23:56 上传
50.jpg (41.74 KB, 下载次数: 293)
23:56 上传
51.jpg (265.41 KB, 下载次数: 293)
23:56 上传
52.jpg (56.89 KB, 下载次数: 291)
23:56 上传
53.jpg (481.67 KB, 下载次数: 292)
23:56 上传
54.jpg (74.36 KB, 下载次数: 294)
23:56 上传
55.jpg (247.73 KB, 下载次数: 292)
23:56 上传
56.jpg (53.03 KB, 下载次数: 288)
23:56 上传
57.jpg (216.63 KB, 下载次数: 292)
23:56 上传
58.jpg (42.4 KB, 下载次数: 273)
23:56 上传
59.jpg (460.29 KB, 下载次数: 274)
23:56 上传
60.jpg (70.74 KB, 下载次数: 271)
23:56 上传
61.jpg (478.99 KB, 下载次数: 274)
23:56 上传
62.jpg (74.38 KB, 下载次数: 271)
23:56 上传
63.jpg (255.08 KB, 下载次数: 279)
23:56 上传
64.jpg (54.34 KB, 下载次数: 278)
23:56 上传
65.jpg (487.47 KB, 下载次数: 270)
23:56 上传
66.jpg (74.6 KB, 下载次数: 268)
23:56 上传
67.jpg (501.66 KB, 下载次数: 275)
23:56 上传
68.jpg (77.73 KB, 下载次数: 275)
23:56 上传
69.jpg (221.69 KB, 下载次数: 279)
23:56 上传
70.jpg (45.83 KB, 下载次数: 271)
23:56 上传
71.jpg (245.98 KB, 下载次数: 279)
23:56 上传
72.jpg (50.9 KB, 下载次数: 273)
23:56 上传
73.jpg (290.23 KB, 下载次数: 275)
23:56 上传
74.jpg (60.38 KB, 下载次数: 271)
23:56 上传
感谢啊,内牛满面
重返地球 www.zzoo.cc/kehuanpian/32600/
钢铁侠3 www.zzoo.cc/kehuanpian/35133/&
~~~~~~~~~~~~~~~~~~~~~
谢谢楼主 好细呀
www.jiankang01.net
楼主好用心啊
有没有素材下载啊
内牛满面呀~~~~~~~~~~~~~~~~~~~~~~
要是能整成电子书看就好了··
掌握VR游戏制作就等于将前途放在了口袋中
为游戏动画新人、进阶动画师、自由动画师,提供入门、进阶的完整学习流程及方法经验
Powered by程序写累了,就来玩玩酷跑小游戏吧,嘿嘿。
雨松MOMO送你一首歌曲,嘿嘿。
Unity3D研究院之处理摄像机跟随避免相机穿墙拉近或透明的方法(四十四)
Unity3D研究院之处理摄像机跟随避免相机穿墙拉近或透明的方法(四十四)
围观34001次
编辑日期: 字体:
当摄像机处于跟随主角状态时,那么主角移动后很有可能摄像机被别的模型挡住。这样用户体验就非常不好,一般3D游戏在处理视角的时候有两种方法,第一种是让被挡住的模型变成透明,第二种是拉近摄像机。前者时候固定视角游戏使用,后者适合变化视角游戏使用。两个我们都学一学蛤蛤。
如下图所示,MOMO写了一个简单的例子,通过鼠标或触摸来牵引主角向不同的角度移动,旁边有一面墙当主角被这面墙挡住,此时摄像机将拉近。
首先,为了方面鼠标与移动平台上的触摸同时相应我写了一个通用的方法。
包括 开始触摸
触摸中 结束触摸 ,电脑手机都可以用这个方法相应到。
JFConst.cs
123456789101112131415161718192021222324252627282930313233343536373839404142434445
using UnityEngine;using System.Collections;&public class JFConst{& public static&&bool TouchBegin() {
if(Input.GetMouseButtonDown(0))
return true;
if(Input.touchCount & 0 && Input.GetTouch(0).phase == TouchPhase.Began)
return true;
return false; }& public static bool TouchEnd() {
if(Input.GetMouseButtonUp(0))
return true;
if(Input.touchCount & 0 && Input.GetTouch(0).phase == TouchPhase.Ended)
return true;
return false; }& public static bool TouchIng() {
if(Input.GetMouseButton(0))
return true;
}else if(Input.touchCount & 0 && Input.GetTouch(0).phase == TouchPhase.Moved)
return true;
return false; }&}
以前写过一篇文章关于移动主角的,如果对移动主角还有不懂的请看这篇
。 这里我就不解释移动主角这部分的代码了。 下面是角色控制器ThirdPersonController.cs 绑定在主角身上。
下面代码中需要详细看的就是161行到174行 ,这部分就是根据触摸屏幕的2D坐标计算主角在3D世界中移动的坐标。
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456
using UnityEngine;using System.Collections;&/** *&&@Author :
*/&[RequireComponent(typeof(CharacterController))]&public class ThirdPersonController : MonoBehaviour {&public AnimationClip idleAnimation ;public AnimationClip walkAnimation ;public AnimationClip runAnimation ;public AnimationClip jumpPoseAnimation;&public float walkMaxAnimationSpeed&&= 0.75f;public float trotMaxAnimationSpeed&&= 1.0f;public float runMaxAnimationSpeed&&= 1.0f;public float jumpAnimationSpeed&&= 1.15f;public float landAnimationSpeed&&= 1.0f;&private Animation _animation;&enum CharacterState{ Idle = 0, Walking = 1, Trotting = 2, Running = 3, Jumping = 4,}&private CharacterState _characterState;&// The speed when walkingpublic float walkSpeed = 2.0f;// after trotAfterSeconds of walking we trot with trotSpeedpublic float trotSpeed = 4.0f;// when pressing "Fire3" button (cmd) we start runningpublic float runSpeed = 6.0f;&public float inAirControlAcceleration = 3.0f;&// How high do we jump when pressing jump and letting go immediatelypublic float jumpHeight = 0.5f;&// The gravity for the characterpublic float gravity = 20.0f;// The gravity in controlled descent modepublic float speedSmoothing = 10.0f;public float rotateSpeed = 500.0f;public float trotAfterSeconds = 3.0f;&public bool canJump = true;&private float jumpRepeatTime = 0.05f;private float jumpTimeout = 0.15f;private float groundedTimeout = 0.25f;&// The camera doesnt start following the target immediately but waits for a split second to avoid too much waving around.private float lockCameraTimer = 0.0f;&// The current move direction in x-zprivate Vector3 moveDirection = Vector3.zero;// The current vertical speedprivate float verticalSpeed = 0.0f;// The current x-z move speedprivate float moveSpeed = 0.0f;&// The last collision flags returned from controller.Moveprivate CollisionFlags collisionFlags; &// Are we jumping? (Initiated with jump button and not grounded yet)private bool jumping = false;private bool jumpingReachedApex = false;&// Are we moving backwards (This locks the camera to not do a 180 degree spin)private bool movingBack = false;// Is the user pressing any keys?private bool isMoving = false;// When did the user start walking (Used for going into trot after a while)private float walkTimeStart = 0.0f;// Last time the jump button was clicked downprivate float lastJumpButtonTime = -10.0f;// Last time we performed a jumpprivate float lastJumpTime = -1.0f;&// the height we jumped from (Used to determine for how long to apply extra jump power after jumping.)private float lastJumpStartHeight = 0.0f;&private Vector3 inAirVelocity = Vector3.zero;&private float lastGroundedTime = 0.0f;&private bool isControllable = true;&void Awake (){ moveDirection = transform.TransformDirection(Vector3.forward);& _animation = GetComponent&Animation&(); if(!_animation)
Debug.Log("The character you would like to control doesn't have animations. Moving her might look weird.");& /*public var idleAnimation : AnimationCpublic var walkAnimation : AnimationCpublic var runAnimation : AnimationCpublic var jumpPoseAnimation : AnimationC */ if(!idleAnimation) {
_animation = null;
Debug.Log("No idle animation found. Turning off animations."); } if(!walkAnimation) {
_animation = null;
Debug.Log("No walk animation found. Turning off animations."); } if(!runAnimation) {
_animation = null;
Debug.Log("No run animation found. Turning off animations."); } if(!jumpPoseAnimation && canJump) {
_animation = null;
Debug.Log("No jump animation found and the character has canJump enabled. Turning off animations."); }&}&void UpdateSmoothedMovementDirection (){& Transform cameraTransform = Camera.main.transform; bool grounded = IsGrounded();& // Forward vector relative to the camera along the x-z plane Vector3 forward = cameraTransform.TransformDirection(Vector3.forward); forward.y = 0; forward = forward.normalized;& // Right vector relative to the camera // Always orthogonal to the forward vector Vector3 right = new Vector3(forward.z, 0, -forward.x);& float v = Input.GetAxisRaw("Vertical"); float h = Input.GetAxisRaw("Horizontal");& // Are we moving backwards or looking backwards if (v & -0.2f)
movingBack = true; else
movingBack = false;& bool wasMoving = isMoving; isMoving = Mathf.Abs (h) & 0.1f || Mathf.Abs (v) & 0.1f;& // Target direction relative to the camera Vector3 targetDirection = h * right + v * forward;& if(JFConst.TouchIng()) {
Vector3 vpos3 = Camera.main.WorldToScreenPoint(transform.position);
Vector2 vpos2 = new Vector2 (vpos3.x,vpos3.y);
Vector2 input = new Vector2 (Input.mousePosition.x,Input.mousePosition.y);
if(Vector2.Distance(vpos2,input) & 10.0f)
Vector2 normalied =
((vpos2 - input)).normalized;
targetDirection = new Vector3(normalied.x,0.0f,normalied.y) ;
float y = Camera.main.transform.rotation.eulerAngles.y;
targetDirection = Quaternion.Euler(0f,y - 180,0f) * targetDirection; &
} } & // Grounded controls if (grounded) {
// Lock camera for short period when transitioning moving & standing still
lockCameraTimer += Time.deltaTime;
if (isMoving != wasMoving)
lockCameraTimer = 0.0f;&
// We store speed and direction seperately,
// so that when the character stands still we still have a valid forward direction
// moveDirection is always normalized, and we only update it if there is user input.
if (targetDirection != Vector3.zero)
// If we are really slow, just snap to the target direction
if (moveSpeed & walkSpeed * 0.9f && grounded)
moveDirection = targetDirection.normalized;
// Otherwise smoothly turn towards it
moveDirection = Vector3.RotateTowards(moveDirection, targetDirection, rotateSpeed * Mathf.Deg2Rad * Time.deltaTime, 1000);&
moveDirection = moveDirection.normalized;
// Smooth the speed based on the current target direction
float curSmooth = speedSmoothing * Time.deltaTime;&
// Choose target speed
//* We want to support analog input but make sure you cant walk faster diagonally than just forward or sideways
float targetSpeed = Mathf.Min(targetDirection.magnitude, 1.0f);&
_characterState = CharacterState.Idle;&
// Pick speed modifier
if (Input.GetKey (KeyCode.LeftShift) | Input.GetKey (KeyCode.RightShift))
targetSpeed *= runSpeed;
_characterState = CharacterState.Running;
else if (Time.time - trotAfterSeconds & walkTimeStart)
targetSpeed *= trotSpeed;
_characterState = CharacterState.Trotting;
targetSpeed *= walkSpeed;
_characterState = CharacterState.Walking;
moveSpeed = Mathf.Lerp(moveSpeed, targetSpeed, curSmooth);&
// Reset walk time start when we slow down
if (moveSpeed & walkSpeed * 0.3f)
walkTimeStart = Time.time; } // In air controls else {
// Lock camera while in air
if (jumping)
lockCameraTimer = 0.0f;&
if (isMoving)
inAirVelocity += targetDirection.normalized * Time.deltaTime * inAirControlAcceleration; }&}&void ApplyJumping (){ // Prevent jumping too fast after each other if (lastJumpTime + jumpRepeatTime & Time.time)
return;& if (IsGrounded()) {
// - Only when pressing the button down
// - With a timeout so you can press the button slightly before landing
if (canJump && Time.time & lastJumpButtonTime + jumpTimeout) {
verticalSpeed = CalculateJumpVerticalSpeed (jumpHeight);
SendMessage("DidJump", SendMessageOptions.DontRequireReceiver);
} }}&void ApplyGravity (){ if (isControllable) // don't move player at all if not controllable. {
// Apply gravity
bool jumpButton = Input.GetButton("Jump");&
// When we reach the apex of the jump we send out a message
if (jumping && !jumpingReachedApex && verticalSpeed &= 0.0f)
jumpingReachedApex = true;
SendMessage("DidJumpReachApex", SendMessageOptions.DontRequireReceiver);
if (IsGrounded ())
verticalSpeed = 0.0f;
verticalSpeed -= gravity * Time.deltaTime; }}&float CalculateJumpVerticalSpeed (float targetJumpHeight){ // From the jump height and gravity we deduce the upwards speed // for the character to reach at the apex. return Mathf.Sqrt(2 * targetJumpHeight * gravity);}&void&&DidJump (){ jumping = true; jumpingReachedApex = false; lastJumpTime = Time.time; lastJumpStartHeight = transform.position.y; lastJumpButtonTime = -10;& _characterState = CharacterState.Jumping;}&void&&Update() {& if (!isControllable) {
// kill all inputs if not controllable.
Input.ResetInputAxes(); }& if (Input.GetButtonDown ("Jump")) {
lastJumpButtonTime = Time.time; }& UpdateSmoothedMovementDirection();& // Apply gravity // - extra power jump modifies gravity // - controlledDescent mode modifies gravity ApplyGravity ();& // Apply jumping logic ApplyJumping ();& // Calculate actual motion Vector3 movement = moveDirection * moveSpeed + new Vector3 (0, verticalSpeed, 0) + inAirVelocity; movement *= Time.deltaTime;& // Move the controller CharacterController controller = GetComponent&CharacterController&(); collisionFlags = controller.Move(movement);& // ANIMATION sector if(_animation) {
if(_characterState == CharacterState.Jumping)
if(!jumpingReachedApex) {
_animation[jumpPoseAnimation.name].speed = jumpAnimationSpeed;
_animation[jumpPoseAnimation.name].wrapMode = WrapMode.ClampForever;
_animation.CrossFade(jumpPoseAnimation.name);
_animation[jumpPoseAnimation.name].speed = -landAnimationSpeed;
_animation[jumpPoseAnimation.name].wrapMode = WrapMode.ClampForever;
_animation.CrossFade(jumpPoseAnimation.name);
if(controller.velocity.sqrMagnitude & 0.1f) {
_animation.CrossFade(idleAnimation.name);
if(_characterState == CharacterState.Running) {
_animation[runAnimation.name].speed = Mathf.Clamp(controller.velocity.magnitude, 0.0f, runMaxAnimationSpeed);
_animation.CrossFade(runAnimation.name);
else if(_characterState == CharacterState.Trotting) {
_animation[walkAnimation.name].speed = Mathf.Clamp(controller.velocity.magnitude, 0.0f, trotMaxAnimationSpeed);
_animation.CrossFade(walkAnimation.name);
else if(_characterState == CharacterState.Walking) {
_animation[walkAnimation.name].speed = Mathf.Clamp(controller.velocity.magnitude, 0.0f, walkMaxAnimationSpeed);
_animation.CrossFade(walkAnimation.name);
} } // ANIMATION sector& // Set rotation to the move direction if (IsGrounded()) {&
transform.rotation = Quaternion.LookRotation(moveDirection);& } else {
Vector3 xzMove = movement;
xzMove.y = 0;
if (xzMove.sqrMagnitude & 0.001f)
transform.rotation = Quaternion.LookRotation(xzMove);
} } & // We are in jump mode but just became grounded if (IsGrounded()) {
lastGroundedTime = Time.time;
inAirVelocity = Vector3.zero;
if (jumping)
jumping = false;
SendMessage("DidLand", SendMessageOptions.DontRequireReceiver);
} }}&void&&OnControllerColliderHit (ControllerColliderHit hit ){// Debug.DrawRay(hit.point, hit.normal); if (hit.moveDirection.y & 0.01f)
return;}&float GetSpeed () { return moveSpeed;}&public bool IsJumping () { return jumping;}&bool IsGrounded () { return (collisionFlags & CollisionFlags.CollidedBelow) != 0;}&Vector3 GetDirection () { return moveDirection;}&public bool IsMovingBackwards () { return movingBack;}&public float GetLockCameraTimer (){ return lockCameraTimer;}&bool IsMoving (){ return Mathf.Abs(Input.GetAxisRaw("Vertical")) + Mathf.Abs(Input.GetAxisRaw("Horizontal")) & 0.5f;}&bool HasJumpReachedApex (){ return jumpingReachedApex;}&bool IsGroundedWithTimeout (){ return lastGroundedTime + groundedTimeout & Time.time;}&void Reset (){ gameObject.tag = "Player";}&}
如此我们就可以通过鼠标与触摸牵引控制主角移动了,别急这紧紧是开始,下面是本章的要点。
这里我们分析一下摄像机到底什么时候该拉近,什么时候该不拉近。 我的作法是这样的,当角色移动的时候我会从主角身上向摄像机方向发射一条射线,如果射线碰撞到的第一个对象是“摄像机” 那么就标示主角和摄像机之间没有别的模型挡住,此时摄像机就不应该拉近。如果射线碰撞到的第一个对象不是摄像机,那么就标示主角和摄像机之间有别的模型所挡住,此时取得射线与别的模型碰撞的3D坐标接着将“摄像机”的坐标移动到这个坐标上即可。
如下图所示,(红色表示由主角发射到摄像机的射线)主角身后的射线没有被别的模型挡住,射线机不会拉近。
如下图所示,MOMO改变了一下主角的位置,此时主角身后的射向已经被墙挡住,这时把摄像机的坐标移动到被墙挡住点的坐标,这样摄像机就拉近了。
原理大概就是这样,接着我们学习一下这段代码该如何来写。
MyCamera.cs 挂在射线机上
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
using UnityEngine;using System.Collections;&public class MyCamera : MonoBehaviour{&&&&&//摄像机朝向的目标模型 public Transform target; //摄像机与模型保持的距离 public float distance = 10.0f; //射线机与模型保持的高度 public float height = 5.0f; //高度阻尼 public float heightDamping = 2.0f; //旋转阻尼 public float rotationDamping = 3.0f; //主角对象 private GameObject controller; & void Start() {
//得到主角对象
controller = GameObject.FindGameObjectWithTag("Player"); }& void Update() {& }& void LateUpdate () {
// Early out if we don't have a target
if (!target)
//当鼠标或者手指在触摸中时
if(JFConst.TouchIng())
bool follow = true; &&&&&&&&//计算相机与主角Y轴旋转角度的差。
float abs = Mathf.Abs(transform.rotation.eulerAngles.y - controller.transform.rotation.eulerAngles.y);
//abs等于180的时候标示摄像机完全面对这主角, 》130 《 230 表示让面对的角度左右偏移50度
//这样做是不希望摄像机跟随主角,具体效果大家把代码下载下来看看,这样的摄像机效果很好。
if(abs & 130 && abs & 230)
follow = false;
follow = true;
float wantedRotationAngle = target.eulerAngles.y;
float wantedHeight = target.position.y + height;&
float currentRotationAngle = transform.eulerAngles.y;
float currentHeight = transform.position.y;&
//主角面朝射线机 和背对射线机 计算正确的位置
if(follow)
currentRotationAngle = Mathf.LerpAngle (currentRotationAngle, wantedRotationAngle, rotationDamping * Time.deltaTime);
currentHeight = Mathf.Lerp (currentHeight, wantedHeight, heightDamping * Time.deltaTime);
Quaternion currentRotation = Quaternion.Euler (0, currentRotationAngle, 0);
Vector3 positon = target.position;
positon -= currentRotation * Vector3.forward * distance;
positon = new Vector3(positon.x,currentHeight,positon.z);
transform.position = Vector3.Lerp(transform.position,positon,Time.time);&
Vector3 positon = target.position;
Quaternion cr = Quaternion.Euler (0, currentRotationAngle, 0); &
positon += cr * Vector3.back * distance;
positon = new Vector3(positon.x,target.position.y + height,positon.z);
transform.position = Vector3.Lerp(transform.position,positon,Time.time);
&&&&//这里是计算射线的方向,从主角发射方向是射线机方向
Vector3 aim = target.position;
//得到方向
Vector3 ve = (target.position - transform.position).normalized;
float an = transform.eulerAngles.y;
aim -= an * ve ;
&&&&//在场景视图中可以看到这条射线
Debug.DrawLine(target.position,aim,Color.red);
&&&&//主角朝着这个方向发射射线
RaycastHit hit;
if(Physics.Linecast(target.position,aim,out hit))
string name =&&hit.collider.gameObject.tag;
if(name != "MainCamera" && name !="terrain")
//当碰撞的不是摄像机也不是地形 那么直接移动摄像机的坐标
transform.position = hit.point;&
// 让射线机永远看着主角
transform.LookAt (target); & }&}
牛头人被墙挡住了,摄像机直接拉近了,小牛头人是不是很帅气?哈哈哈!!
最后雨松MOMO把源码放出来,希望大家学习愉快,哇咔咔。。。
下载地址:
补充 :摄像机遮挡物体透明。
遮挡透明最简单的办法就是修改材质的透明度,前提需要把材质设置成支持透明通道的 shader Transparent 。 如下图所示,摄像机挡住的那面墙已经成透明状态了。
看看代码是如何写的,把上述代码MyCamera.cs 简单的改一下就可以。 主要是92行到101行。
代码核心就是通过射线得到碰撞模型的材质,然后修改材质的透明度。color.a就是透明度 1是完全不透明,0是完全透明。注意一定是支持透明通道的模型才可以。lastobj是记录上次透明的对象,用于模型透明还原使用。
123456789101112131415161718192021222324
if(Physics.Linecast(target.position,aim,out hit))
GameObject obj = hit.collider.gameObject;&
string name =&&obj.tag;
if(name != "MainCamera" && name !="terrain")
Color color = obj.renderer.material.color;
color.a = 0.5f;
obj.renderer.material.SetColor("_Color", color);&
lastobj = obj;&
if(lastobj != null)
Color color = lastobj.renderer.material.color;
color.a = 1f;
lastobj.renderer.material.SetColor("_Color", color);
最后,假设你的模型做的非常大,贴图材质也非常的多,你像透明其中一小部分那么上述方法就不合适了,除非把他们都拆出来。我觉得也可以自己写shader实现。我们的项目采用了摄像机拉近的方式。欢迎讨论!!!
回答楼下问题:上帝视角代码,看到楼下有朋友问我,那么我就贴出来,其实很简单。下面代码挂在摄像机上, target就是角色对象,distance 是摄像机与角色的距离 height是摄像机与角色的高度。在编辑器中手动调节即可。
1234567891011121314151617181920212223242526
using UnityEngine;using System.Collections;&public class ICamera : MonoBehaviour {&public Transform target;// The distance in the x-z plane to the targetpublic float distance = 10.0f;// the height we want the camera to be above the targetpublic float height = 5.0f;&void LateUpdate () { // Early out if we don't have a target if (!target)
return;& // Set the position of the camera on the x-z plane to: // distance meters behind the target transform.position = target.position; transform.position -=&&Vector3.forward * distance; transform.position = new Vector3(transform.position.x,transform.position.y + height,transform.position.z);& // Always look at the target transform.LookAt (target); }}
回答问题 :摄像机抖动如何修改
今天微薄上有个朋友问我这样的问题,我在这里解答一下。
来福12345:我又厚颜无耻的来了,您的《Unity3D的研究院之处理摄像机跟随避免相机穿墙拉近或透明的方法(四十四)》对于不规则的物体该怎么弄,我是直接在unity上弄了几个山脉,由于地面凹凸不平,沿着山走的时候发现摄像机会一直透视,而且抖动的很厉害,请问该怎么解决啊
1.从设计上避免射线遇到一些复杂的面,如下图所示,红颜色是主角身后的射线,当主角身后的射线碰撞到这样的面,如果此时移动速快快一些摄像机肯定会抖动。 这里最好直接删除Mesh Collider 换成BoxCollider 效率还可以得到提升。产经设计这块我觉得可以参考一下魔兽世界,我在项目中遇到这样问题的地方就是 比较小的门(棱角那种) 或者这样的树。
2.但是还有一些比较特殊的地方,如果你的项目必需使用MeshColider 的话 我建议你写触发脚本来修改摄像机,假设 当摄像机被挡住后,变成跟随视角,只到摄像机没被挡住的时候在回到原来视角。
3.我检查了一下上面的代码中我们在加一个判断,应该就可以解决大部分问题、在LateUpdate () 中最后加入代码
12345678910111213141516
if(!closer)
transform.position = positon;&
float dis = Vector3.Distance(transform.position,controller.transform.position);
if(dis & 8)
distance = dis;
closer = false;
bool closer 是表示是否拉近。 当摄像机被挡住的时候这个数值等于
12345678910
if(Physics.Linecast(tirggerTaget,aim,out hit))
string name =&&hit.collider.gameObject.tag;
if(name != "MainCamera")
closer = true;
transform.position = hit.point;
distance = Vector3.Distance(transform.position,controller.transform.position) - 2f;
当closer等于假的时候,此时直接修更新摄像机的位置,因为没被挡住。 当closer等于真的时候,摄像机已经被挡住了,我们不修改摄像机的位置,计算摄像机保证不被挡住时,摄像机此时和主角的距离是多少,然后修改distance全局变量即可。当摄像机不被遮挡的时候在恢复之前的距离。 如有问题请留言,我会即时解答。。 谢谢
//补充/////////
之前的代码还是有点问题,后来我又仔细的重构了一下摄像机的代码。下面的代码在我的项目中已经完美无暇的模拟摄像机拉近了。。 代码对外有两个公有类型, 一个是模型的 一个是模型位置 与头顶的偏移, 因为射线应该是重头顶向后发射的。
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
using UnityEngine;using System.Collections;using System.Threading;&public class PersonCamera : MonoBehaviour {& public const&&float DISTANCE_DEAFULT = 8.0f; private float distance = 0.0f; public Transform target; public float target_offsety = 1.8f; private Vector3 payerTaget; & void Awake() {
distance = DISTANCE_DEAFULT;
payerTaget =&&new Vector3(target.position.x,target.position.y + target_offsety , target.position.z);
Quaternion cr = Quaternion.Euler (30f, transform.eulerAngles.y, 0);
Vector3 positon = payerTaget;
positon += cr * Vector3.back * distance;
transform.position = positon;
transform.LookAt(payerTaget); } void LateUpdate() {&
payerTaget =&&new Vector3(target.position.x,target.position.y + target_offsety , target.position.z);
Quaternion cr = Quaternion.Euler (30f, transform.eulerAngles.y, 0);
Vector3 positon = payerTaget + (cr * Vector3.back * distance);
RaycastHit []hits = Physics.RaycastAll(new Ray(payerTaget,(positon -payerTaget).normalized));
distance = DISTANCE_DEAFULT;
if(hits.Length & 0)
RaycastHit stand = hits[0];
foreach(RaycastHit hit in hits)
if(hit.collider.gameObject.tag == "terrain")
if(hit.distance & stand.distance)
stand = hit;
Debug.Log(stand.point + " " +stand.collider.gameObject.tag);
string tag = stand.collider.gameObject.tag;
distance = Vector3.Distance(stand.point,payerTaget);
if(distance & DISTANCE_DEAFULT)
distance = DISTANCE_DEAFULT;
positon = payerTaget + (cr * Vector3.back * distance);
&&&&transform.position = Vector3.Lerp(transform.position,positon,0.3f);;&
transform.LookAt(payerTaget);&
Debug.DrawRay(payerTaget,positon -payerTaget,Color.red);
本文固定链接:
转载请注明:
雨松MOMO提醒您:亲,如果您觉得本文不错,快快将这篇文章分享出去吧 。另外请点击网站顶部彩色广告或者捐赠支持本站发展,谢谢!
作者:雨松MOMO
专注移动互联网,Unity3D游戏开发
如果您愿意花10块钱请我喝一杯咖啡的话,请用手机扫描二维码即可通过支付宝直接向我捐款哦。
您可能还会对这些文章感兴趣!

我要回帖

更多关于 unity3d 编辑器扩展 的文章

 

随机推荐