荏苒追寻个人博客

做一个有追求的青年


  • 首页

  • 关于

  • 标签

  • 分类

  • 归档

  • 日程表

Unity杂项记录

发表于 2023-10-13 | 分类于 Unity

Unity Editor Basic

  • Unity 界面导航

官方Game Kit类型的资源学习感受

  1. 不跟着教程一步步操作的话,自己去摸索是浪费时间;
  2. 通过Game Kit来了解资源包中的具体资源的使用,包括prefab、camera、material、script的使用,使用过程中根据效果看看具体的实现(点击具体的GameObject,通过Inspector 来查看该GameObject上使用的具体 组件的实现,了解组件都有哪些属性;
  3. 熟练使用组件定制的菜单,来完成自己的关卡设计,从易到难,逐步加大场景的复杂度。

捕鱼达人

  1. 捕鱼达人各种实现
    1. 鱼群生成算法;
    2. 鱼的生成、按路径游动、鱼的转向;
    3. 武器、等级、装备变化实现;
    4. 捕鱼概率及伤害实现;

跑酷游戏

  1. 背景的移动;
  2. 障碍物的生成;
  3. 角色的控制
    1. 跳跃及二级跳;
    2. 滑行
    3. 冲刺实现
  4. 道具奖励

跑酷游戏二级跳

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
bool isOnGround = true;
int jumpCount = 0;
int jumpMaxCount = 2;
void Update()
{
if (Input.GetKeyDown(KeyCode.Space) && (isOnGround || jumpCount < jumpMaxCount))
{
jumpCount++;
playerRb.AddForce(Vector3.up * jumpForce, ForceMode.Impulse);
}
}

private void OnCollisionEnter(Collision collision)
{
if (collision.gameObject.CompareTag("Ground"))
{
dirtParticle.Play();
isOnGround = true;
jumpCount = 0;
}
}

二级跳问题

  1. 第一次跳跃下降时进行二级跳无法跳高

未命名

发表于 2023-10-13 | 分类于 Unity

未命名

发表于 2023-10-13

参考文章:

  • 发哥的第一人称视角游戏

Linux杂谈

发表于 2023-10-13 | 分类于 Linux

https://rainmonth.github.io/posts/L180130.html

看源码时多少会解除到一些Linux相关的内容,做个记录

一些Linux函数

  • fnctl,文件控制函数

  • socketpair,创建了一对无名的套接字描述符(只能在AF_UNIX域中使用),描述符存储于一个二元数组,eg. s[2] .这对套接字可以进行双工通信,每一个描述符既可以读也可以写

Python 爬虫——爬取宅男女神网图片

发表于 2023-10-13 | 分类于 Python , 爬虫

https://rainmonth.github.io/posts/c455eeb0.html

Python 爬虫——爬虫基础问题解决

发表于 2023-10-13 | 分类于 Python , 爬虫

https://rainmonth.github.io/posts/6be31a91.html

摘要

本文主要介绍爬虫学习所要掌握的基础知识,主要包括Web开发相关基础知识(Html、Css等)、Python相关基础知识、几个简单的Python库的使用等。还需要一些知识储备,比如:

  • re 模块,python 正则基础;

  • requests,用于获取网页内容,供后续处理;

  • lxml,用于处理 Html文档中的 元素;

  • 常用的爬虫策略与反爬策略;

阅读全文 »

Unity 错误解决方案记录

发表于 2023-10-13 | 分类于 Unity

问题1

问题描述

错误 CS8357 指定的版本字符串中包含与确定性不兼容的通配符。从版本字符串删除通配符,或者禁用此编译的确定性

解决方案

C#脚本中版本号中使用了通配符,如1.0.*与确定性不兼容,将通配符改成具体的版本号就可以。

问题2

问题描述

No cloud project ID was found by the Analytics SDK. This means Analytics events will not be sent. Please make sure to link your cloud project in the Unity editor to fix this problem.

解决方案:

在Unity的 Services菜单中找到配置,填写一些信息后就可以了,用现有的License创建一个project Id

问题3

问题描述

Deterministic compilation failed. You can disable Deterministic builds in Player Settings

解决方案

确定性编译失败。您可以在播放器设置中禁用确定性构建。Edit->Project Setting,左边找到Player,然后右边Other Setting,进度条拖动到最底部,Use deterministic compilation 取消勾选即可

问题4

问题描述

下载了一个可在Windows、Mac以及Android跑的demo,想更改下build设置跑起来看看下过,结果发现切换到Android平台是,右下方的build and run不可点击

解决方案

先点击switch platform,然后等切换编译完成后,build and run即可点击

问题5

问题描述

导入模型显示不对,过黑过于黯淡

解决方案

原因就是模型使用的Shader在Unity版本升级后被自动替换了,需要找到这个模型,然后找到合适的Shader进行替换,也可以用下面的脚本进行批量替换

Unity批量替换材质 Shader 脚本

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
public class ChangeShader : EditorWindow
{
[MenuItem("*Tool*/Change Shader")]
public static void ShowWindow()
{
EditorWindow editorWindow = GetWindow(typeof(ChangeShader));
editorWindow.autoRepaintOnSceneChange = false;
}

//当前shader
public Shader currentShader;
//目标shader
public Shader changeShader;
public HashSet<Material> mat = new HashSet<Material>();

private void OnGUI()
{
currentShader = EditorGUILayout.ObjectField("查找 shader", currentShader, typeof(Shader),false) as Shader;
changeShader = EditorGUILayout.ObjectField("替换 shader", changeShader, typeof(Shader), false) as Shader;
if (GUILayout.Button("Change"))
{
Change();
}

if (mat.Count > 0)
{
//界面中显示被替换的材质球
EditorGUILayout.LabelField("替换掉的材质:");
foreach (var material in mat)
{
if (material != null)
EditorGUILayout.ObjectField(material, typeof(Material), false);
}

if (GUILayout.Button("Clear"))
mat.Clear();
}
}

public void Change()
{
mat.Clear();
// 加载的路径需要加后缀名
if (currentShader == null || changeShader == null)
{
return;
}

var allfiles = Directory.GetFiles("Assets/", "*.mat", SearchOption.AllDirectories);
var length = allfiles.Length;
var count = 0;
for (var i = 0; i < length; i++)
{
var file = allfiles[i];
//显示替换进度
if (EditorUtility.DisplayCancelableProgressBar("Changing", file, i / (float) length))
{
break;
}
//根据地址读取材质球
Material tempMat = AssetDatabase.LoadAssetAtPath<Material>(file);
if (tempMat.shader == currentShader)
{
tempMat.shader = changeShader;
mat.Add(tempMat);
// Debug.Log($"Change {tempMat.name} from {currentShader.name} to {changeShader.name}");
count++;
}
}

AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
EditorUtility.ClearProgressBar();
EditorUtility.DisplayDialog("一共修改:" + count + "个材质", "就绪", "OK");
}
}

知乎

Unity有哪些适合拿来练手的游戏项目?

Unity技术交流

官方入门教程

Python 资料收录

发表于 2023-10-13 | 分类于 Python

本文链接:https://rainmonth.github.io/posts/P200202.html

这里主要收集Python相关的项目、文章。文章通常来源于微信公众号、掘金社区等。

问题记录

Tinker

  1. PyCharm 上,Python 3.9版本上使用tinker的Entry控件不显示?

    1
    问题原因:Python版本适配问题,升级到Python 3.12后 Entry、Label等组件都能正常显示了

    注意:问题一直搜不到答案是,尝试Google搜索一下。

  2. 定义好Tinker组件后,记得调用pack方法

正则表达式

  1. Python 正则表达式的转义能不要就不要,影响性能,如非特殊位置的 ‘-‘: 当 ‘-‘’ 不处于特殊位置(如不在方括号内的范围定义中)时,它不需要被转义。

Java 设计模式——备忘录模式

发表于 2023-10-13 | 分类于 Java , 设计模式

模式定义

备忘录模式(Memento Pattern)保存一个对象的某个状态,以便在适当的时候恢复对象。备忘录模式属于行为型模式。

所谓备忘录模式就是在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样可以在以后将对象恢复到原先保存的状态。通常需要一个备忘录类来存储对象状态,然后还有一个类来管理存储的对象状态,以便在需要的时候对对象进行恢复。

模式示例

下面来看具体示例,备忘录主要有三个角色:备忘录对象,要备忘的目标对象,备忘录管理。首先看备忘录对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**
* 备忘录类,保存了一个状态,同时还有保存的日期,根据日期可以来检索保存的备忘
*/
public class Backup {
private String state;
private Date date;

public Backup(String state) {
this.state = state;
date = new Date();
}

public String getState() {
return state;
}

public void setState(String state) {
this.state = state;
}

public Date getDate() {
return date;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/**
* 备忘录管理对象,可以读取或者添加备忘录
*/
public class Recovery {
private List<Backup> backups = new ArrayList<Backup>();

public void add(Backup backup) {
backups.add(backup);
}

public Backup retrieve(Date date) {
for (Backup backup : backups) {
if (backup.getDate().equals(date)) {
backups.remove(backup);
return backup;
}
}
return null;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/**
* 需要备忘的对象
*/
public class Application {
private String state = "default setting";

public Backup backup() {
return new Backup(state);
}

public void recover(Backup backup) {
this.state = backup.getState();
}

public void setState(String state) {
this.state = state;
}

public String getState() {
return state;
}
}

客户端调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class Main {

public static void main(String[] args) {
Application application = new Application();
Recovery recovery = new Recovery();

System.out.println(application.getState());

Backup backup = application.backup(); // 建立备忘
recovery.add(backup); // 加入备忘录

application.setState("customer setting");
System.out.println(application.getState());

Date date = backup.getDate(); // 假设 date 是使用者自行设定所要取得的还原时间!
application.recover(recovery.retrieve(date)); // 取出备忘录来还原
System.out.println(application.getState());
}

}
1
2
3
default setting
customer setting
default setting

模式总结

备忘录模式的核心思想就是在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,以便在需要的时候可以从保存的状态中恢复。

优缺点

  • 优点
    1. 给用户提供了一种可以恢复状态的机制,可以使用户能够比较方便地回到某个历史的状态。
    2. 实现了信息的封装,使得用户不需要关心状态的保存细节。
  • 缺点
    1. 消耗资源。如果类的成员变量过多,势必会占用比较大的资源,而且每一次保存都会消耗一定的内存。

使用场景

通常使用在需要保存/恢复数据的相关状态场景,在保存状态后,还提供一个可回滚的操作。也就是需要实现存档和读档这两个过程。

  • 游戏存档非常适合使用备忘录模式
  • 撤销操作
  • 数据库事务管理

注意事项

  1. 为了符合迪米特原则,还要增加一个管理备忘录的类。
  2. 为了节约内存,可使用原型模式+备忘录模式

Java 设计模式13——模板方法模式

发表于 2023-10-13 | 分类于 Java , 设计模式

模板定义

在模板模式(Template Pattern)中,一个抽象类公开定义了执行它的方法的方式/模板。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。这种类型的设计模式属于行为型模式。

通常这个抽象类定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。

模式示例

下面以一个奶茶店为例,咖啡馆主要生成两种饮品:咖啡和茶。准备的的大体流程相似:烧水,煮,导入杯中给客户,还可以视客户需要加一些额外的调剂品,如牛奶和糖。上面的过程可以抽象出如下过程。

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

public abstract class CaffeineBeverage {

private boolean isNeedToAddCondiments = true;

/**
* 通用算法
* 大体的制作流程
*/
public final void prepareRecipe() {
boilWater();
brew();
pourInCup();
if (customerWantsCondiments()) {
addCondiments();
}
}

/**
* 不同的部分,由子类实现
*/
protected abstract void brew();

/**
* 不同的部分,由子类实现
*/
protected abstract void addCondiments();

private void boilWater() {
System.out.println("Boiling water");
}

private void pourInCup() {
System.out.println("Pouring into cup");
}

/**
* 询问是否需要额外添加品
* @return true if needed
*/
public boolean customerWantsCondiments() {
return isNeedToAddCondiments;
}

/**
* 设置是否需要额外添加品
*/
public void setCustomerWantsCondiments(boolean needToAddCondiment) {
isNeedToAddCondiments = needToAddCondiment;
}
}

Coffee的具体流程

1
2
3
4
5
6
7
8
9
10
11
12
13
public class Coffee extends CaffeineBeverage {

@Override
protected void brew() {
System.out.println("Dripping Coffee through filter");
}

@Override
protected void addCondiments() {
System.out.println("Adding Sugar and Milk");
}

}
1
2
3
4
5
6
7
8
9
10
11
12
13
public class Tea extends CaffeineBeverage {

@Override
protected void brew() {
System.out.println("Steeping the tea");
}

@Override
protected void addCondiments() {
System.out.println("Adding Lemon");
}

}

奶茶店实现如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class TeaHouseClient {
public static void main(String[] args) {

Tea tea = new Tea();
Coffee coffee = new Coffee();

System.out.println("\nMaking tea...");
tea.prepareRecipe();

System.out.println("\nMaking coffee...");
coffee.setCustomerWantsCondiments(false);
coffee.prepareRecipe();

}
}

输出结果如下

1
2
3
4
5
6
7
8
9
10
Making tea...
Boiling water
Steeping the tea
Pouring into cup
Adding Lemon

Making coffee...
Boiling water
Dripping Coffee through filter
Pouring into cup

上面示例中,prepareRecipe()就是抽象出来的通用算法,不管什么新的品类,都要经过这个操作,需要写在模板类中。像addCondiments()和brew()等抽象方法他们视不同的品类而不同,因而交给子类来实现。

模式总结

开发过程中,一些流程化的操作中,通常会有通用的流程,为了避免在每一次实现中都进行一次编码,我们可以把通用的不同抽象出来,定义成模板,不同的部分定义成抽象方法,供子类去实现,这就是模板方法模式。Android开发中的经常封装的BaseActivity通常都会应用这种方式。

优缺点

  • 优点
    1. 封装不变部分,扩展可变部分;
    2. 提取公共代码,便于维护;
    3. 行为由父类控制,子类实现。
  • 缺点
    • 每一个不同的实现都需要一个子类来实现,导致类的个数增加,使得系统更加庞大。

注意事项

  1. 为防止恶意操作,一般模板方法都加上 final 关键词。
  2. 通用操作在抽象类实现,其他步骤在子类实现。

使用场景

  1. 有多个子类共有的方法,且逻辑相同。
  2. 重要的、复杂的方法,可以考虑作为模板方法。
<i class="fa fa-angle-left" aria-label="上一页"></i>1234…22<i class="fa fa-angle-right" aria-label="下一页"></i>

216 日志
43 分类
43 标签
GitHub
© 2025 Randy Zhang
由 Hexo 强力驱动
|
主题 — NexT.Gemini v6.1.0