10月1日 npc对话 参考https://blog.csdn.net/weixin_43673589/article/details/106559650 对象层级 将Canvas设为世界空间以绑定
10月1日
npc对话
参考https://blog.csdn.net/weixin_43673589/article/details/106559650
对象层级
将Canvas
设为世界空间以绑定在npc身上
给npc添加脚本
using System.Collections;using System.Collections.Generic;using UnityEngine;using UnityEngine.UI;public class NPC : MonoBehaviour { public GameObject dialog; public GameObject tip; public Text text; public float showTime = 2; private float showTimer; private bool isShow = false; private bool isEnter = false; void Start () { tip.SetActive (false); dialog.SetActive (false); showTimer = -1; } void Update () { if (isEnter) { if (Input.GetKeyDown (KeyCode.E)) { Showdialog (); } } if (isShow) { showTimer -= Time.deltaTime; if (showTimer < 0) { dialog.SetActive (false); isShow = false; } } } private void OnTriggerEnter2D (Collider2D other) { if (other.tag == "Player") { tip.SetActive (true); isEnter = true; } } private void OnTriggerExit2D (Collider2D other) { if (other.tag == "Player") { isEnter=false; tip.SetActive (false); } } public void Showdialog () { text.text = "你好!"; isShow = true; showTimer = showTime; dialog.SetActive (true); tip.SetActive (false); }}
npc要添加Collider2D
,并勾选触发器选项
玩家要有Collider2D
和Rigidbody2D
关于Collider2D
的碰撞https://blog.csdn.net/youxijishu/article/details/104259317
效果
爬梯子
制作一个平台以及一个梯子
给梯子添加collider
,并在顶端的位置再添加一个带有collider
的对象
增加的代码
using System.Collections;using System.Collections.Generic;using UnityEngine;public class Player : MonoBehaviour { public Transform ladderCheck; //梯子 public Transform ladderTopCheck; public LayerMask ladder; public LayerMask ladderTop; public bool isLadder, isLadderTop; void Update () { if (isLadder) { if (!isLadderTop) { if (Input.GetKey (KeyCode.W)) { rb.velocity = new Vector2 (rb.velocity.x, 1); } } if (Input.GetKey (KeyCode.S)) { if (isGround) { platform.GetComponent<Collider2D> ().enabled = false; } rb.velocity = new Vector2 (rb.velocity.x, -1); } } } private void FixedUpdate () { isLadderTop = Physics2D.OverlapCircle (ladderTopCheck.position, 0.1f, ladderTop); //判断是否在梯子顶端 } private void OnTriggerEnter2D (Collider2D other) { if (other.tag == "Ladder") { isLadder = true; transform.GetComponent<Rigidbody2D> ().gravityScale = 0; if (!isLadderTop) { platform.GetComponent<Collider2D> ().enabled = false; } } } private void OnTriggerExit2D (Collider2D other) { if (other.tag == "Ladder") { isLadder = false; transform.GetComponent<Rigidbody2D> ().gravityScale = 1; platform.GetComponent<Collider2D> ().enabled = true; } }}
ladderTop
的检测方式和ground
的检测方式一样
ladder
和ladderTop
的collider
的最高点要一致
效果
角色冲刺
关键代码
使用MovePosition
函数移动到指定位置
if (Input.GetKey(KeyCode.LeftShift)) { Vector2 velocity = new Vector2(horizontalMove, 0)*sprintDistance; rb.MovePosition(rb.position + velocity * Time.fixedDeltaTime);}
效果
释放火球
准备一张火球的图片,制作成prefab
玩家脚本添加
using System.Collections;using System.Collections.Generic;using UnityEngine;public class Player : MonoBehaviour { public int playerDirection; //玩家面对方向 public int playerType; //玩家元素 void Update () { if(Input.GetMouseButtonDown(0)){ skillRelease(); } if(Input.GetKeyDown(KeyCode.D)){ playerDirection=1; //向右 } if(Input.GetKeyDown(KeyCode.A)){ playerDirection=-1; //向右 } } //技能释放 private void skillRelease () { switch (playerType) { case 1: GameObject objPrefab = (GameObject) Resources.Load ("Prefabs/playerFireBall"); objPrefab.transform.GetComponent<playerFireBall>().moveDirection=playerDirection; Instantiate (objPrefab, transform.position, transform.rotation); break; case 2: break; case 3: break; } }}
火球脚本
using System.Collections;using System.Collections.Generic;using UnityEngine;public class playerFireBall : MonoBehaviour{ // Start is called before the first frame update public float moveSpeed; public float maxMoveDistance; //最大移动距离 private float moveDistance; //移动距离 public int moveDirection; //移动方向 private Vector3 startPosition; //起始位置 void Start() { startPosition=transform.position; } void Update() { transform.Translate(Vector3.right*moveDirection *moveSpeed * Time.deltaTime); moveDistance=Mathf.Abs((transform.position-startPosition).x); if(moveDistance>=maxMoveDistance){ Destroy(gameObject); } }}
效果
火焰与草丛互动
制作三种不同状态的草丛prefab
,设定同一个taggrass
,并添加collider
将它们都添加同一个Object.cs
脚本
using System.Collections;using System.Collections.Generic;using UnityEngine;public class Object : MonoBehaviour { public bool isOnFire; public bool isFired; public int objType; private float fireTimer; public float fireTime; private float growTimer; //生长时间 public float growTime; void Start () { } void Update () { if (isOnFire) { //正在燃烧 if (fireTimer < fireTime) { fireTimer += Time.deltaTime; } else { GameObject firedGrassPb=(GameObject) Resources.Load ("Prefabs/firedGrass"); firedGrassPb.transform.GetComponent<Object>().isFired=true; Instantiate(firedGrassPb,transform.position,transform.rotation); Destroy (gameObject); } } if (isFired) { //烧完了 if (growTimer < growTime) { growTimer += Time.deltaTime; } else { GameObject grassPb=(GameObject) Resources.Load ("Prefabs/grass"); Instantiate(grassPb,transform.position,transform.rotation); Destroy (gameObject); } } }}
fireGrass
预制体勾选isOnFire
,firedGrass
预制体勾选isFired
fireTime
,GrowTime
分别表示烧完,生长所需时间
修改火球的脚本
playerFireBall.cs
private void OnTriggerEnter2D (Collider2D other) { if (other.tag == "grass") { if (!other.transform.GetComponent<Object> ().isOnFire && !other.transform.GetComponent<Object> ().isFired) { Destroy (gameObject); GameObject fireGrassPb = (GameObject) Resources.Load ("Prefabs/fireGrass"); fireGrassPb.transform.GetComponent<Object> ().isOnFire = true; Instantiate (fireGrassPb, other.transform.position, other.transform.rotation); Destroy (other.gameObject); } }}
效果
10月2日
元素交互
水与火
照葫芦画瓢,做一个放水球的功能,新建名为playerSkill.cs
的脚本,并把之前playerFireBall.cs
中的内容复制过去,然后给水球和火球都绑定playerSkill
脚本
假设潮湿的草遇到火元素会烘干,然后有蒸发的特效,燃烧的草遇到水则会被扑灭
简单制作一个蒸发的粒子特效
首先新建一个water
材质球,然后修改Shader,选择水滴的图片
然后新建steam
粒子,将water
作为材质,并适当修改粒子的属性
再制作潮湿和烘干的草丛预制体
被扑灭草丛
修改playerSkill.cs
using System.Collections;using System.Collections.Generic;using UnityEngine;public class playerSkill : MonoBehaviour { private enum skillTypes { fire, water, wind } public int skillType; //技能类型 public float moveSpeed; //移动速度 public float maxMoveDistance; //最大移动距离 private float moveDistance; //移动距离 public int moveDirection; //移动方向 private Vector3 startPosition; //起始位置 void Start () { startPosition = transform.position; //其实位置 } void Update () { //移动超过一定距离销毁 transform.Translate (Vector3.right * moveDirection * moveSpeed * Time.deltaTime); moveDistance = Mathf.Abs ((transform.position - startPosition).x); if (moveDistance >= maxMoveDistance) { Destroy (gameObject); } } private void OnTriggerEnter2D (Collider2D other) { //元素与物品交互(碰撞) if (other.tag == "grass") { Object grass = other.transform.GetComponent<Object> (); switch (skillType) { //火技能 case (int) skillTypes.fire: //草丛没有燃烧 没有烧尽 没有潮湿 没有被扑灭 if (!grass.isOnFire && !grass.isFired && !grass.isOnWater&&!grass.isOutfire) { Destroy (gameObject); GameObject fireGrassPb = (GameObject) Resources.Load ("Prefabs/fireGrass"); Instantiate (fireGrassPb, other.transform.position, other.transform.rotation); Destroy (other.gameObject); } //潮湿的草丛 if (grass.isOnWater) { Destroy (gameObject); GameObject waterGrassPb = (GameObject) Resources.Load ("Prefabs/dryingGrass"); Instantiate (waterGrassPb, other.transform.position, other.transform.rotation); Destroy (other.gameObject); GameObject steam = (GameObject) Resources.Load ("Prefabs/steam"); Instantiate (steam); } break; //水技能 case (int) skillTypes.water: //草丛没有燃烧 没有烧尽 没有被扑灭 if (!grass.isOnFire && !grass.isFired&&!grass.isOutfire) { Destroy (gameObject); GameObject waterGrassPb = (GameObject) Resources.Load ("Prefabs/waterGrass"); Instantiate (waterGrassPb, other.transform.position, other.transform.rotation); Destroy (other.gameObject); } //草丛正在燃烧 if (grass.isOnFire) { } break; } } }}
Object.cs
using System.Collections;using System.Collections.Generic;using UnityEngine;public class Object : MonoBehaviour { public bool isOnFire; public bool isFired; //烧尽 public bool isOnWater; public bool isDrying; //烘干 public int objType; private float fireTimer; public float fireTime; private float growTimer; //生长时间 public float growTime; public float dryTime; //烘干时间 private float dryTimer; void Start () { } void Update () { if (isOnFire) { //正在燃烧 if (fireTimer < fireTime) { fireTimer += Time.deltaTime; } else { GameObject firedGrassPb=(GameObject) Resources.Load ("Prefabs/firedGrass"); Instantiate(firedGrassPb,transform.position,transform.rotation); Destroy (gameObject); } } if (isFired) { //烧完了 if (growTimer < growTime) { growTimer += Time.deltaTime; } else { GameObject grassPb=(GameObject) Resources.Load ("Prefabs/grass"); Instantiate(grassPb,transform.position,transform.rotation); Destroy (gameObject); } } if(isDrying){ if (dryTimer<dryTime) { dryTimer += Time.deltaTime; } else { GameObject grassPb=(GameObject) Resources.Load ("Prefabs/grass"); Instantiate(grassPb,transform.position,transform.rotation); Destroy (gameObject); } } }}
效果
火与风
风有概率吹出草丛里的道具
制作风技能
制作加血道具
为了方便给Object
添加isNormal
属性,表示正常状态
prob
表示发生某事件概率
给grass
预制件勾选上
playerSkill
脚本
case (int) skillTypes.wind: if (grass.isNormal) { Destroy (gameObject); //概率吹出道具 int prob = Random.Range (0, 100); if (prob < other.transform.GetComponent<Object> ().prob) { GameObject hearteGrassPb = (GameObject) Resources.Load ("Prefabs/heart"); Instantiate (hearteGrassPb, other.transform.position, other.transform.rotation); } Destroy (other.gameObject); }
效果
风吹向燃烧的草丛会引发爆炸
制作爆炸预制件(同蒸发效果)
使主角与爆炸粒子碰撞会掉血
首先开启粒子的碰撞效果
然后在player
的OnParticleCollision
方法中写碰撞粒子后的事件
public Transform hearts; //血条void Start () { hearts = GameObject.Find ("hearts").transform; bloodNum = hearts.GetComponent<hearts> ().bloodNum;}private void OnParticleCollision (GameObject other) { if (other.tag == "explode") { changeBlood (-1); }}private void OnTriggerEnter2D (Collider2D other) { if(other.tag=="heart"){ changeBlood(1); Destroy(other.gameObject); }}private void changeBlood (int type) { //1是加血 -1是减血 if (type == 1) { if (bloodNum < maxBloodtNum) { bloodNum += 1; hearts.GetComponent<hearts> ().changeBlood(type); } } else if (type == -1) { if (bloodNum > 0) { bloodNum -= 1; hearts.GetComponent<hearts> ().changeBlood(type); } }}
heart.cs
using System.Collections;using System.Collections.Generic;using UnityEngine;using UnityEngine.UI;public class hearts : MonoBehaviour { public Transform heart0; public Transform heart1; public Transform heart2; public List<Transform> heartList; public int maxBloodNum; public int bloodNum; void Start () { heartList = new List<Transform> (); heartList.Add (heart0); heartList.Add (heart1); heartList.Add (heart2); if (bloodNum != maxBloodNum) { for (int i = 0; i < maxBloodNum - bloodNum; i++) { heartList[maxBloodNum-i-1].GetChild (1).GetComponent<Image> ().enabled = false; } } } void Update () { } public void changeBlood (int type) { if (type == 1) { if (bloodNum < maxBloodNum) { heartList[bloodNum].GetChild (1).GetComponent<Image> ().enabled = true; bloodNum += 1; } } else if (type == -1) { if (bloodNum > 0) { bloodNum -= 1; heartList[bloodNum].GetChild (1).GetComponent<Image> ().enabled = false; } } }}
效果
10月3日
主角攻击(击剑)
准备一张剑的图片,添加collider
,勾选触发器
添加一个剑平移(击剑)的简单动画
绑定在角色身上
player
public GameObject sword; //武器 剑void Start () { sword = GameObject.Find ("sword");}void Update () { //普通攻击 if (Input.GetMouseButtonDown (0)) { sword.transform.GetComponent<Animation>().Play ("swordAttack"); }}
效果
新物品:箱子
箱子与元素的交互 部分遵循与草丛的交互规则
普通箱子不可打破,潮湿箱子可以被打破
制作不同的箱子,添加collider
和rigidbody
给Object
添加
private void OnTriggerStay2D (Collider2D other) { if (objType == (int) objTypes.woodenBox) { //潮湿的箱子可打破 if(isOnWater){ if (other.tag == "sword") { if (other.transform.GetComponent<Animation> ().IsPlaying ("swordAttack")) { Destroy (gameObject); } } } }}
效果
相机跟随
给相机添加CameraFollow.cs
脚本
using System.Collections;using System.Collections.Generic;using UnityEngine;public class CameraFollow : MonoBehaviour { public Transform player; //设定一个角色能看到的最远值 public float Ahead; //设置一个摄像机要移动到的点 public Vector3 targetPos; //设置一个缓动速度插值 public float smooth; void Start () { } void Update () { targetPos = new Vector3 (player.position.x, gameObject.transform.position.y, gameObject.transform.position.z); if (player.position.x > 0f) { targetPos = new Vector3 (player.position.x + Ahead, gameObject.transform.position.y, gameObject.transform.position.z); } else { targetPos = new Vector3 (player.position.x - Ahead, gameObject.transform.position.y, gameObject.transform.position.z); } transform.position = Vector3.Lerp (transform.position, targetPos, smooth * Time.deltaTime); }}
切换角色时改变相机的player
注意要传入Instantiate
后的对象而不是prefab
对象
Player.cs
if (Input.GetKeyDown (KeyCode.Alpha1)) { GameObject objPrefab = (GameObject) Resources.Load ("Prefabs/playerCat"); GameObject player= Instantiate (objPrefab, transform.position, transform.rotation); changePlayerCamera (player); DestroyImmediate (gameObject);}private void changePlayerCamera (GameObject player) { GameObject camera = GameObject.Find ("MainCamera"); camera.GetComponent<CameraFollow> ().player = player.transform;}
效果
视差效果
https://www.bilibili.com/video/BV1Zx411X72x?from=search&seid=14704518843659195740
随便制作两个背景
BackgroundParallax.cs
using System.Collections;using System.Collections.Generic;using UnityEngine;public class BackgroundParallax : MonoBehaviour { public new Camera camera; //摄像机对象 public Transform[] backgrounds; //不同层次的背景 public float[] parallaxScales; //每个层次的视差比例(即背景与摄影机的移动量的比例) public float smoothTime; //看做是速度的倒数就好~ private Vector3 lastCameraPosition; //上一次相机的位置,用于计算滚动量 private Vector3 velocity; //速度向量,Vector3.SmoothDamp用到的变量 void Start () { lastCameraPosition = camera.transform.position; //初始化lastCameraPosition velocity = Vector3.zero; //初始化velocity } void Update () { //遍历每个层次的背景 for (int i = 0, count = backgrounds.Length; i < count; i++) { Vector3 parallax = (lastCameraPosition - camera.transform.position) * parallaxScales[i]; //计算滚动量(滚动距离=摄像机移动距离*视差比例) parallax.z = 0f; //设置z轴滚动量为0,防止背景前后移动 Vector3 target = backgrounds[i].position + parallax; //目标坐标=当前背景坐标+滚动量 backgrounds[i].position = Vector3.SmoothDamp (backgrounds[i].position, target, ref velocity, smoothTime); //用Vector3.SmoothDamp将背景平滑移动 } lastCameraPosition = camera.transform.position; //更新lastCameraPosition }}
将该脚本绑定到摄像机上,调整参数
效果