Unity3D研究院之IOS自定义游戏摇杆与飞机平滑的移动(十一)

本文介绍了如何在Unity3D中使用标准资源的Joystick.js脚本来创建一个触摸游戏摇杆,适用于iPhone等全触摸设备。通过调整摇杆的属性,如死区和归一化,可以实现360度平滑控制。同时,展示了如何结合摇杆反馈控制游戏对象,例如飞机的移动。此外,提供了代码示例展示如何获取摇杆位置并应用于游戏对象的移动逻辑。
摘要由CSDN通过智能技术生成

 移动开发游戏中使用到的触摸游戏摇杆在iPhone上是非常普遍的,毕竟是全触摸屏手机,今天MOMO 通过一个小例子和大家讨论Unity3D 中如何自定义一个漂亮的全触摸游戏摇杆。

       值得高兴的是,Unity3D 游戏引擎的标准资源中已经帮助我们封装了一个游戏摇杆脚本,所以实现部分的代码可以完全借助它的,具体调用需要我们自己来。

 Joystick.js是官方提供的脚本,具体代码如下,有兴趣的朋友可以仔细研究研究,MOMO就不多说啦。哇咔咔~

C#

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

//

// Joystick.js

// Penelope iPhone Tutorial

//

// Joystick creates a movable joystick (via GUITexture) that

// handles touch input, taps, and phases. Dead zones can control

// where the joystick input gets picked up and can be normalized.

//

// Optionally, you can enable the touchPad property from the editor

// to treat this Joystick as a TouchPad. A TouchPad allows the finger

// to touch down at any point and it tracks the movement relatively

// without moving the graphic

//

 

@script RequireComponent( GUITexture )

 

// A simple class for bounding how far the GUITexture will move

class Boundary

{

var min : Vector2 = Vector2.zero;

var max : Vector2 = Vector2.zero;

}

 

static private var joysticks : Joystick[]; // A static collection of all joysticks

static private var enumeratedJoysticks : boolean = false;

static private var tapTimeDelta : float = 0.3; // Time allowed between taps

 

var touchPad : boolean; // Is this a TouchPad?

var touchZone : Rect;

var deadZone : Vector2 = Vector2.zero; // Control when position is output

var normalize : boolean = false; // Normalize output after the dead-zone?

var position : Vector2; // [-1, 1] in x,y

var tapCount : int; // Current tap count

 

private var lastFingerId = -1; // Finger last used for this joystick

private var tapTimeWindow : float; // How much time there is left for a tap to occur

private var fingerDownPos : Vector2;

private var fingerDownTime : float;

private var firstDeltaTime : float = 0.5;

 

private var gui : GUITexture; // Joystick graphic

private var defaultRect : Rect; // Default position / extents of the joystick graphic

private var guiBoundary : Boundary = Boundary(); // Boundary for joystick graphic

private var guiTouchOffset : Vector2; // Offset to apply to touch input

private var guiCenter : Vector2; // Center of joystick

 

function Start()

{

// Cache this component at startup instead of looking up every frame

gui = GetComponent( GUITexture );

 

// Store the default rect for the gui, so we can snap back to it

defaultRect = gui.pixelInset;

 

    defaultRect.x += transform.position.x * Screen.width;// + gui.pixelInset.x; // -  Screen.width * 0.5;

    defaultRect.y += transform.position.y * Screen.height;// - Screen.height * 0.5;

 

    transform.position.x = 0.0;

    transform.position.y = 0.0;

 

if ( touchPad )

{

// If a texture has been assigned, then use the rect ferom the gui as our touchZone

if ( gui.texture )

touchZone = defaultRect;

}

else

{

// This is an offset for touch input to match with the top left

// corner of the GUI

guiTouchOffset.x = defaultRect.width * 0.5;

guiTouchOffset.y = defaultRect.height * 0.5;

 

// Cache the center of the GUI, since it doesn't change

guiCenter.x = defaultRect.x + guiTouchOffset.x;

guiCenter.y = defaultRect.y + guiTouchOffset.y;

 

// Let's build the GUI boundary, so we can clamp joystick movement

guiBoundary.min.x = defaultRect.x - guiTouchOffset.x;

guiBoundary.max.x = defaultRect.x + guiTouchOffset.x;

guiBoundary.min.y = defaultRect.y - guiTouchOffset.y;

guiBoundary.max.y = defaultRect.y + guiTouchOffset.y;

}

}

 

function Disable()

{

gameObject.active = false;

enumeratedJoysticks = false;

}

 

function ResetJoystick()

{

// Release the finger control and set the joystick back to the default position

gui.pixelInset = defaultRect;

lastFingerId = -1;

position = Vector2.zero;

fingerDownPosition = Vector2.zero;

 

if ( touchPad )

gui.color.a = 0.025;

}

 

function IsFingerDown() : boolean

{

return (lastFingerId != -1);

}

 

function LatchedFinger( fingerId : int )

{

// If another joystick has latched this finger, then we must release it

if ( lastFingerId == fingerId )

ResetJoystick();

}

 

function Update()

{

if ( !enumeratedJoysticks )

{

// Collect all joysticks in the game, so we can relay finger latching messages

joysticks = FindObjectsOfType( Joystick );

enumeratedJoysticks = true;

}

 

var count = Input.touchCount;

 

// Adjust the tap time window while it still available

if ( tapTimeWindow > 0 )

tapTimeWindow -= Time.deltaTime;

else

tapCount = 0;

 

if ( count == 0 )

ResetJoystick();

else

{

for(var i : int = 0;i < count; i++)

{

var touch : Touch = Input.GetTouch(i);

var guiTouchPos : Vector2 = touch.position - guiTouchOffset;

 

var shouldLatchFinger = false;

if ( touchPad )

{

if ( touchZone.Contains( touch.position ) )

shouldLatchFinger = true;

}

else if ( gui.HitTest( touch.position ) )

{

shouldLatchFinger = true;

}

 

// Latch the finger if this is a new touch

if ( shouldLatchFinger && ( lastFingerId == -1 ¦¦ lastFingerId != touch.fingerId ) )

{

 

if ( touchPad )

{

gui.color.a = 0.15;

 

lastFingerId = touch.fingerId;

fingerDownPos = touch.position;

fingerDownTime = Time.time;

}

 

lastFingerId = touch.fingerId;

 

// Accumulate taps if it is within the time window

if ( tapTimeWindow > 0 )

tapCount++;

else

{

tapCount = 1;

tapTimeWindow = tapTimeDelta;

}

 

// Tell other joysticks we've latched this finger

for ( var j : Joystick in joysticks )

{

if ( j != this )

j.LatchedFinger( touch.fingerId );

}

}

 

if ( lastFingerId == touch.fingerId )

{

// Override the tap count with what the iPhone SDK reports if it is greater

// This is a workaround, since the iPhone SDK does not currently track taps

// for multiple touches

if ( touch.tapCount > tapCount )

tapCount = touch.tapCount;

 

if ( touchPad )

{

// For a touchpad, let's just set the position directly based on distance from initial touchdown

position.x = Mathf.Clamp( ( touch.position.x - fingerDownPos.x ) / ( touchZone.width / 2 ), -1, 1 );

position.y = Mathf.Clamp( ( touch.position.y - fingerDownPos.y ) / ( touchZone.height / 2 ), -1, 1 );

}

else

{

// Change the location of the joystick graphic to match where the touch is

gui.pixelInset.x =  Mathf.Clamp( guiTouchPos.x, guiBoundary.min.x, guiBoundary.max.x );

gui.pixelInset.y =  Mathf.Clamp( guiTouchPos.y, guiBoundary.min.y, guiBoundary.max.y );

}

 

if ( touch.phase == TouchPhase.Ended ¦¦ touch.phase == TouchPhase.Canceled )

ResetJoystick();

}

}

}

 

if ( !touchPad )

{

// Get a value between -1 and 1 based on the joystick graphic location

position.x = ( gui.pixelInset.x + guiTouchOffset.x - guiCenter.x ) / guiTouchOffset.x;

position.y = ( gui.pixelInset.y + guiTouchOffset.y - guiCenter.y ) / guiTouchOffset.y;

}

 

// Adjust for dead zone

var absoluteX = Mathf.Abs( position.x );

var absoluteY = Mathf.Abs( position.y );

 

if ( absoluteX < deadZone.x )

{

// Report the joystick as being at the center if it is within the dead zone

position.x = 0;

}

else if ( normalize )

{

// Rescale the output after taking the dead zone into account

position.x = Mathf.Sign( position.x ) * ( absoluteX - deadZone.x ) / ( 1 - deadZone.x );

}

 

if ( absoluteY < deadZone.y )

{

// Report the joystick as being at the center if it is within the dead zone

position.y = 0;

}

else if ( normalize )

{

// Rescale the output after taking the dead zone into account

position.y = Mathf.Sign( position.y ) * ( absoluteY - deadZone.y ) / ( 1 - deadZone.y );

}

}

单击Create 创建一个GUI Texture,命名为Joy ,它用来显示游戏摇杆,如下图所示将摇杆的图片资源,与摇杆的脚本连线赋值给Joy.  Pixel Inset 中可以设置摇杆的显示位置与显示宽高。

 

 

 

到这一步 build and run 就可以在iPhone上看到这个游戏摇杆,并且可以通过触摸它,360度平滑过度。

在屏幕中绘制一个飞机,通过游戏摇杆去控制飞机的移动。

创建一个脚本,命名为Main.js 如下图所示  将 Main.js 、joy、plan 分别 绑定在Main Camera 上。

 

 

 

moveJoystick.position.x;

moveJoystick.position.y; 

这两个值是非常重要的两个信息,它们的取值范围是 -1 到 +1 ,表示 用户触摸摇杆的位置, 上 下 左 右 的信息。

 

C#

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

//游戏摇杆对象

var moveJoystick : Joystick;

 

//飞机的贴图

var plan : Texture;

 

//飞机在屏幕中的坐标

var x = 0;

var y = 0;

 

//避免飞机飞出屏幕,分别是X、Y最大坐标,最小坐标是0、0

var cross_x = 0;

var cross_y = 0;

 

//飞机移动的速度

var planSpeed = 20;

 

function Start() {

//初始化赋值

x = 100;

y = 100;

cross_x = Screen.width -  plan.width;

cross_y = Screen.height -  plan.height;

 

}

 

function Update () {

//得到游戏摇杆的反馈信息,得到的值是 -1 到 +1 之间

 

var touchKey_x =  moveJoystick.position.x;

var touchKey_y =  moveJoystick.position.y;

 

//摇杆向左

if(touchKey_x == -1){

x -= planSpeed;

 

}

//摇杆向右

else if(touchKey_x == 1){

x += planSpeed;

 

}

//摇杆向上

   if(touchKey_y == -1){

y += planSpeed;

 

}

//摇杆向下

else if(touchKey_y == 1){

y -= planSpeed;

 

}

 

//防止飞机飞出屏幕,出界检测

if(x < 0){

x = 0;

}else if(x > cross_x){

x = cross_x;

}

 

   if(y < 0){

y = 0;

}else if(y > cross_y){

y = cross_y;

}

}

 

function OnGUI () {

 

  //将飞机绘制在屏幕中

  GUI.DrawTexture(Rect(x,y,128,128),plan);  

 

}

导出 build and run  看看在iPhone 上的效果,通过触摸游戏摇杆可以控制飞机的移动啦,不错吧,哇咔咔~~

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值