1. 钻水管
思路:预先录制跳水管动画,使用Animator,在满足条件时(人物接触水管且按空格键)播放动画和音效。
过程:默认状态>跳入水管>人物缩小>位移到另一个水管>人物放大>恢复默认状态
主要函数:
(1)协程函数
StartCoroutine(jumpintotube)和IEnumerator jumpintotube()配合使用。从跳入管子到恢复默认状态的所有动作均在IEnumerator中完成。
等待时间的格式:yield return new WaitForSeconds(float);
(2)线性插值函数
设置:计时器(初始值为0,动态值为 += Time.deltaTime)、变化前的位置/大小和变化后的位置/大小。
gameObject.transform.localScale = Vector3.Lerp(startScaleSize, toScale, counter / duration);
脚本:
using
System
.
Collections
;
using
System
.
Collections
.
Generic
;
using
UnityEngine
;
public
class
PlayerMovement
:
MonoBehaviour
{
public
float
turnSpeed
=
20f
;
Animator
m_Animator
;
Rigidbody
m_Rigidbody
;
Vector3
m_Movement
;
Quaternion
m_Rotation
=
Quaternion
.
identity
;
bool
touchTube
;
public
AudioSource
jump
;
public
AudioSource
intoTube
;
public
float
duration
;
public
GameObject
tube2
;
void
Start
(
)
{
m_Animator
=
GetComponent
<
Animator
>
(
)
;
m_Rigidbody
=
GetComponent
<
Rigidbody
>
(
)
;
}
void
FixedUpdate
(
)
{
float
horizontal
=
Input
.
GetAxis
(
"Horizontal"
)
;
float
vertical
=
Input
.
GetAxis
(
"Vertical"
)
;
m_Movement
.
Set
(
horizontal
,
0f
,
vertical
)
;
m_Movement
.
Normalize
(
)
;
bool
hasHorizontalInput
=
!
Mathf
.
Approximately
(
horizontal
,
0f
)
;
bool
hasVerticalInput
=
!
Mathf
.
Approximately
(
vertical
,
0f
)
;
bool
isRunning
=
hasHorizontalInput
||
hasVerticalInput
;
m_Animator
.
SetBool
(
"IsRunning"
,
isRunning
)
;
Vector3
desiredForward
=
Vector3
.
RotateTowards
(
transform
.
forward
,
m_Movement
,
turnSpeed
*
Time
.
deltaTime
,
0f
)
;
m_Rotation
=
Quaternion
.
LookRotation
(
desiredForward
)
;
if
(
touchTube
==
true
)
{
if
(
Input
.
GetKeyDown
(
"space"
)
)
{
m_Animator
.
SetBool
(
"IsJumping"
,
true
)
;
jump
.
Play
(
)
;
StartCoroutine
(
jumpintotube
(
)
)
;
}
}
}
IEnumerator
jumpintotube
(
)
{
yield
return
new
WaitForSeconds
(
1f
)
;
intoTube
.
Play
(
)
;
float
counter
=
0
;
Vector3
startScaleSize
=
gameObject
.
transform
.
localScale
;
Vector3
startPosition
=
gameObject
.
transform
.
position
;
Vector3
toScale
=
new
Vector3
(
0.1f
,
0.1f
,
0.1f
)
;
Vector3
toScale2
=
new
Vector3
(
1f
,
1f
,
1f
)
;
Vector3
toPosition
=
new
Vector3
(
0.98f
,
0
,
0.38f
)
;
Vector3
toPosition2
=
new
Vector3
(
tube2
.
transform
.
position
.
x
,
tube2
.
transform
.
position
.
y
+
0.7f
,
tube2
.
transform
.
position
.
z
)
;
while
(
counter
<
duration
)
{
counter
+=
Time
.
deltaTime
;
gameObject
.
transform
.
localScale
=
Vector3
.
Lerp
(
startScaleSize
,
toScale
,
counter
/
duration
)
;
gameObject
.
transform
.
position
=
Vector3
.
Lerp
(
startPosition
,
toPosition
,
counter
/
duration
)
;
yield
return
null
;
}
gameObject
.
transform
.
position
=
new
Vector3
(
tube2
.
transform
.
position
.
x
,
tube2
.
transform
.
position
.
y
,
tube2
.
transform
.
position
.
z
)
;
jump
.
Stop
(
)
;
intoTube
.
Stop
(
)
;
m_Animator
.
SetBool
(
"IsJumping"
,
false
)
;
yield
return
new
WaitForSeconds
(
1f
)
;
intoTube
.
Play
(
)
;
float
counter2
=
0
;
Vector3
startPosition2
=
gameObject
.
transform
.
position
;
while
(
counter2
<
duration
)
{
counter2
+=
Time
.
deltaTime
;
gameObject
.
transform
.
localScale
=
Vector3
.
Lerp
(
startScaleSize
,
toScale2
,
counter2
/
duration
)
;
gameObject
.
transform
.
position
=
Vector3
.
Lerp
(
startPosition2
,
toPosition2
,
counter2
/
duration
)
;
yield
return
null
;
}
}
void
OnCollisionEnter
(
Collision
collision
)
{
if
(
collision
.
collider
.
tag
==
"Tube"
)
{
touchTube
=
true
;
}
}
void
OnAnimatorMove
(
)
{
m_Rigidbody
.
MovePosition
(
m_Rigidbody
.
position
+
m_Movement
*
Time
.
deltaTime
*
2f
)
;
m_Rigidbody
.
MoveRotation
(
m_Rotation
)
;
}
}
2. 吃金币
思路:金币的消失与重现,本来想用SetActive来做,结果发现金币物体设成false以后,碰撞器也随之消失了,所以没法通过OnTriggerExit来变回true。经过研究,最后是用renderer.enabled = false来做,这样只会影响renderer组件,而不会影响碰撞器,就可以通过OnTriggerExit让renderer变回true了
脚本:
using
System
.
Collections
;
using
System
.
Collections
.
Generic
;
using
UnityEngine
;
public
class
CoinMovement
:
MonoBehaviour
{
public
float
speed
;
public
AudioSource
coin
;
public
AudioClip
coinSound
;
public
Renderer
coin_Renderer
;
void
Update
(
)
{
transform
.
Rotate
(
Vector3
.
up
*
Time
.
deltaTime
*
speed
,
Space
.
World
)
;
}
void
OnTriggerEnter
(
Collider
other
)
{
if
(
other
.
gameObject
.
CompareTag
(
"Player"
)
)
{
coin
.
Play
(
)
;
StartCoroutine
(
WaitForSound
(
)
)
;
}
}
IEnumerator
WaitForSound
(
)
{
float
coinSoundDuration
=
coinSound
.
length
;
coin_Renderer
.
enabled
=
false
;
yield
return
new
WaitForSeconds
(
coinSoundDuration
)
;
}
void
OnTriggerExit
(
Collider
other
)
{
if
(
other
.
gameObject
.
CompareTag
(
"Player"
)
)
{
Debug
.
Log
(
"Exit"
)
;
coin_Renderer
.
enabled
=
true
;
}
}
}
示范视频 https://www.bilibili.com/video/BV1qZ4y1w79y/