寫在前面
實現(xiàn)類似于憤怒的小鳥中的彈弓功能。
功能
- 拖拽小鳥松開時發(fā)射
- 拖拽范圍的限制
實現(xiàn)
-
首先要用到Unity中的一個物理組件,Spring Joint 2D往湿。它就是一個彈簧連接,就相當于兩個物體間用彈簧連接一樣研侣。不管兩個物體大于或者小于某固定的距離,都會產(chǎn)生相互作用的力楞泼。而且伴有彈性系數(shù)等驰徊。具體屬性如下圖(001):
001.png 讓物體跟隨鼠標移動,因為鼠標是屏幕坐標系堕阔,需要轉(zhuǎn)化為世界坐標系才能賦值使用棍厂。由于是2D場景,在轉(zhuǎn)化后要修改下z軸超陆,不然會看不到物體牺弹,代碼如下:
transform.position = Camera.main.ScreenToWorldPoint(Input.mousePosition);
transform.position += new Vector3(0, 0, 10);
- 之后給拖拽限定一個范圍,讓物體在有效的范圍內(nèi)移動时呀。對此张漂,在彈弓上(Sprite圖)上創(chuàng)建一個節(jié)點(CenterObject),計算出物體到節(jié)點的方向谨娜,在定義一個距離最大值鹃锈。
if (Vector3.Distance(transform.position, CenterObject.position) > MaxDistance) {
Vector3 pos1 = (transform.position - CenterObject.position).normalized;
pos1 *= MaxDistance;
transform.position = CenterObject.position + pos1;
}
重點討論
憤怒的小鳥的彈弓功能有一個小細節(jié),就是拖拽物體碰到弓柄的時候不會透過弓柄瞧预,而是往上拉到發(fā)射口屎债,這樣顯得更加真實仅政,大致實現(xiàn)方法如下:
1 . 在會發(fā)生碰撞的地方設(shè)置碰撞體,設(shè)置IsTrigger為true盆驹。
2 . 添加監(jiān)聽事件
void OnTriggerEnter2D(Collider2D collider)
{
IsTrigger = true;
}
void OnTriggerExit2D(Collider2D collider)
{
IsTrigger = false;
}
3 . 當觸發(fā)碰撞體時圆丹,將拖拽最大距離縮小,將其拉到發(fā)射口躯喇。當離開碰撞體時辫封,再將距離拉大。注意廉丽,以下代碼中第一個if代碼塊,當物體運動到發(fā)射口時倦微,且此時不再觸發(fā)碰撞體,就不會縮短距離了正压,反之增加距離欣福,這是受跟隨鼠標的影響往下移動又觸發(fā)碰撞體,產(chǎn)生了抖動的情況焦履。要避開這種情況拓劝,就是當物體處于發(fā)射口時不要增加距離。
void OnSetpOver()
{
if (Vector3.Distance(transform.position, ButtomObject.position) < 0.2)
{
IsAddDistance = false;
}
else
IsAddDistance = true;
if (IsTrigger)
{
if (IsMove)
MaxDistance -= 0.1f;
}
else
{
if (IsMove && MaxDistance< 0.9f && IsAddDistance)
{
MaxDistance += 0.1f;
}
}
}
功能源碼
文末有項目下載地址嘉裤,結(jié)合項目更容易理解郑临。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Brid : MonoBehaviour {
//鼠標是否按下
private bool IsClick;
//是否觸發(fā)了碰撞體
private bool IsTrigger;
//鼠標是否在移動
private bool IsMove;
//是否允許拉長距離
private bool IsAddDistance;
//能夠拖拽小鳥的最長距離
public float MaxDistance;
//記錄鼠標0.02s前的位置
private Vector3 firstpos;
//計時
private float timer = 0f;
private SpringJoint2D Sp;
private Rigidbody2D rig2d;
public CapsuleCollider2D TargetCollider;
public LineRenderer right;
public Transform Rightobject;
public Transform ButtomObject;
public Transform Target;
public Transform CenterObject;
public LineRenderer left;
public Transform Leftobject;
void Awake()
{
Sp = GetComponent<SpringJoint2D> ();
rig2d = GetComponent<Rigidbody2D> ();
}
void OnMouseDown()
{
IsClick = true;
rig2d.isKinematic = true;
}
void OnMouseUp()
{
IsClick = false;
rig2d.isKinematic = false;
TargetCollider.enabled = false;
Invoke("Fly", 0.1f);
}
void OnTriggerEnter2D(Collider2D collider)
{
IsTrigger = true;
}
void OnTriggerExit2D(Collider2D collider)
{
IsTrigger = false;
}
void FixedUpdate ()
{
if (IsClick)
{
transform.position = Camera.main.ScreenToWorldPoint(Input.mousePosition);
transform.position += new Vector3(0, 0, 10);
if (Vector3.Distance(transform.position, CenterObject.position) > MaxDistance) {
Vector3 pos1 = (transform.position - CenterObject.position).normalized;
pos1 *= MaxDistance;
transform.position = CenterObject.position + pos1;
}
Line();
OnSetpOver();
}
OnMouseMove();
}
void Fly()
{
Sp.enabled = false;
}
void Line()
{
right.SetPosition (0, Rightobject.position);
right.SetPosition (1, transform.position);
left.SetPosition (0, Leftobject.position);
left.SetPosition (1, transform.position);
}
void Cancel()
{
}
void OnMouseMove()
{
if (timer < 0.02f)
{
firstpos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
timer += Time.fixedDeltaTime;
}
else
{
if (firstpos != Camera.main.ScreenToWorldPoint(Input.mousePosition))
{
IsMove = true;
}
else
IsMove = false;
timer = 0;
}
}
void OnSetpOver()
{
if (Vector3.Distance(transform.position, ButtomObject.position) < 0.2)
{
IsAddDistance = false;
}
else
IsAddDistance = true;
if (IsTrigger)
{
if (IsMove)
MaxDistance -= 0.1f;
}
else
{
if (IsMove && MaxDistance< 0.9f && IsAddDistance)
{
MaxDistance += 0.1f;
}
}
}
}
結(jié)語
以上代碼實現(xiàn)的拖動看起來不是很順暢,更真正的憤怒的小鳥比起來顯得有些僵硬屑宠,如果讀者有更好的解決方案請告訴我厢洞。