Unity记录6.5-动作-连续技

汇总:Unity 记录
开源地址:asd123pwj/asdGame停了七个月,最近看起来又有空了,棒棒。
写的好爽。
摘要:连续技的实现,以及按键判断代码的优化。
设计思路-2024/05/04
- 这次实现的是这七个月心心念念的冲刺,即双击右方向,向右冲刺。
- 基于此实现个连续技。
- 然而,时间过久,系统有点遗忘,所以画个系统框图。
系统框图-2024/05/04
- 用visio画了,挺好的,自动扩页,不愧是专业的,就是容器类型略少。
冲刺-2024/05/05
- 先用shift实现了,感觉之前写的还蛮好的,蛮容易添加功能。
- 实现方式是对自身向指定方向施加一个瞬时的力。
优化即时动作-2024/05/07
- 写连续技的时候,发现套用原先单按键的即时动作不好,综合考虑后,把即时动作都移到一起去了。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
public class InputSingle{
// ---------- events ----------
public Dictionary<string, List<_input_action>> _single2Actions = new();
// ---------- status ----------
public InputInfo _input_info;
public InputSingle(){
init_input2Actions();
}
public void _update(InputInfo input_info){
_input_info = input_info;
if (Input.GetAxisRaw("Horizontal") != 0) action("horizontal");
if (Input.GetAxisRaw("Vertical") != 0) action("vertical");
if (Input.GetButton("Shift")) action("shift");
}
void action(string input_type){
var actions = _single2Actions[input_type];
foreach (var action in actions){ action(_input_info); }
}
void add_action(string input_type, _input_action action) { _single2Actions[input_type].Add(action); }
void clear_action(string input_type) { _single2Actions[input_type].Clear(); }
public void _register_action(string input_type, _input_action action, bool isNew=false){
if (isNew) clear_action(input_type);
add_action(input_type, action);
}
void init_input2Actions(){
// ----- mouse events
_single2Actions.Add("fire1 down", new());
_single2Actions.Add("fire1", new());
_single2Actions.Add("fire2 down", new());
_single2Actions.Add("fire2", new());
_single2Actions.Add("fire3 down", new());
_single2Actions.Add("fire3", new());
// ----- direction events
_single2Actions.Add("horizontal", new());
_single2Actions.Add("vertical", new());
// ----- ability events
_single2Actions.Add("shift", new());
// ----- SL events
_single2Actions.Add("save", new());
_single2Actions.Add("load", new());
}
}
输入状态记录-2024/05/07-2024/05/08
- 为了防止按下的键一直触发连续技,我写了个判断按键是否首次按下的类。
- 太尴尬了,
Input.GetButtonDown
的功能就是在第一次按下时为真,而我拿它判断是否一直按下,导致报错了一会,浪费精力了。 - 不过这个类还是很好的,就是冗余了些。
- 太尴尬了,
- 这个类的目的,是将所有按键的状态(按下、抬起、首次按下、首次抬起)记录到一个字典里,方便直接用键查询。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Tilemaps;
public struct KeyInfo{
public bool isDown;
public bool isUp;
public bool isFirstDown;
public bool isFirstUp;
}
public class InputStatus{
// ---------- Status ----------
public Dictionary<string, KeyInfo> _keyStatus = new();
// ---------- Config ----------
List<string> _input_key = new() {
"Fire1", "Fire2", "Fire3", "Jump", "Shift",
"Up", "Down", "Left", "Right", "Horizontal", "Vertical",
"Save", "Load",
"Number 0", "Number 1", "Number 2", "Number 3", "Number 4", "Number 5", "Number 6", "Number 7", "Number 8", "Number 9",
"Numpad 0", "Numpad 1", "Numpad 2", "Numpad 3", "Numpad 4", "Numpad 5", "Numpad 6", "Numpad 7", "Numpad 8", "Numpad 9",
};
public InputStatus(){
init_keyStatus();
}
public void _update(){
update_keyStatus();
}
void init_keyStatus(){
_keyStatus.Clear();
foreach (string key in _input_key) _keyStatus.Add(key, new());
}
void set_keyStatus(string key, bool isDown){
var keyStatus = _keyStatus[key];
if (isDown){
keyStatus.isFirstDown = !keyStatus.isDown;
keyStatus.isDown = true;
keyStatus.isUp = false;
}
else{
keyStatus.isFirstUp = !keyStatus.isUp;
keyStatus.isUp = true;
keyStatus.isDown = false;
}
_keyStatus[key] = keyStatus;
}
void update_keyStatus(){
foreach (string key in _input_key){
if (key == "Up") set_keyStatus(key, Input.GetAxisRaw("Vertical") > 0);
else if (key == "Down") set_keyStatus(key, Input.GetAxisRaw("Vertical") < 0);
else if (key == "Left") set_keyStatus(key, Input.GetAxisRaw("Horizontal") < 0);
else if (key == "Right") set_keyStatus(key, Input.GetAxisRaw("Horizontal") > 0);
else set_keyStatus(key, Input.GetButton(key));
}
}
}
连续技-2024/05/07-2024/05/08
- 和即时动作那里不一样,连续技这里用类来记录某个技能。
- 这个类记录了包括触发序列,按键间隔,技能。
- 并且判断按键是否满足需求,满足需求则触发。
- 按键的判断是首次按下某键,例如连续两次右方向键,只有右方向键按下的瞬间才会被判断通过,即代码中的
isFirstDown
。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
class ComboAction{
// ---------- Config ----------
public List<string> _combo_sequence;
public float _interval;
public _input_action _action;
// ---------- Status ----------
float last_input_time = 0;
int combo_passed = 0;
public ComboAction(List<string> comboSequence, _input_action action): this(comboSequence, action, 0.4f){}
public ComboAction(List<string> comboSequence, _input_action action, float interval){
_combo_sequence = comboSequence;
_interval = interval;
_action = action;
}
void add_input() { combo_passed += 1; last_input_time = Time.time; }
void clear_input() { combo_passed = 0; last_input_time = 0;}
bool check_full(){ return combo_passed == _combo_sequence.Count; }
bool check_deadline(){ return Time.time - last_input_time > _interval; }
string get_next_key(){ return _combo_sequence[combo_passed]; }
public bool _act(KeyPos keyPos, Dictionary<string, KeyInfo> keyStatus){
if (check_combo(keyStatus)) { _action(keyPos); return true; }
else return false;
}
bool check_combo(Dictionary<string, KeyInfo> keyStatus){
if (keyStatus[get_next_key()].isFirstDown){
if (check_deadline()) {
clear_input();
if (keyStatus[get_next_key()].isFirstDown) add_input();
return false;
}
else add_input();
if (check_full()){
clear_input();
return true;
}
}
return false;
}
}
public class InputCombo{
// ---------- actions ----------
Dictionary<List<string>, ComboAction> _comboActions = new();
public InputCombo(){}
public void _update(KeyPos keyPos, Dictionary<string, KeyInfo> keyStatus){
foreach (var comboAction in _comboActions.Values){
comboAction._act(keyPos, keyStatus);
}
}
public void _register_action(List<string> input_type, _input_action action, bool isNew=false){
if (!_comboActions.ContainsKey(input_type)) _comboActions.Add(input_type, new(input_type, action));
else _comboActions[input_type] = new(input_type, action);
}
}
再次优化的即时技能-2024/05/08
- 上面的连续技写的很好,我很满意,所以我进一步优化了即时技能的代码。
- 从54行缩到39行,还更清楚,爽。
- 和连续技类似,但是判断时机不是首次按下某键,而是按下某键,即一直按下就一直触发。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
class SingleAction{
// ---------- Config ----------
public string _single_key;
public _input_action _action;
public SingleAction(string single_key, _input_action action){
_single_key = single_key;
_action = action;
}
public bool _act(KeyPos keyPos, Dictionary<string, KeyInfo> keyStatus){
if (keyStatus[_single_key].isDown) { _action(keyPos); return true; }
else return false;
}
}
public class InputSingle{
// ---------- actions ----------
Dictionary<string, SingleAction> _singleActions = new();
public InputSingle(){}
public void _update(KeyPos keyPos, Dictionary<string, KeyInfo> keyStatus){
foreach (var comboAction in _singleActions.Values){
comboAction._act(keyPos, keyStatus);
}
}
public void _register_action(string input_type, _input_action action, bool isNew=false){
if (!_singleActions.ContainsKey(input_type)) _singleActions.Add(input_type, new(input_type, action));
else _singleActions[input_type] = new(input_type, action);
}
}
文章目录
关闭
共有 0 条评论