RCT 帮助文档
首页
  • 入门指南
  • 脚本元数据
  • 自定义UI
  • 核心API
  • Chart类
  • 数据类
  • 示例脚本
  • 最佳实践
脚本商店
  • 简体中文
  • English
首页
  • 入门指南
  • 脚本元数据
  • 自定义UI
  • 核心API
  • Chart类
  • 数据类
  • 示例脚本
  • 最佳实践
脚本商店
  • 简体中文
  • English
  • API参考

    • 首页
    • 入门指南
    • 脚本元数据
    • 自定义UI对话框
    • 核心API
    • Chart 类
    • 数据类
    • 示例脚本
    • 最佳实践

最佳实践

本页面提供 RCT Python 脚本开发的最佳实践和注意事项。

开发建议

1. 始终检查返回值

get_current_chart() 可能返回 None,务必检查:

chart = get_current_chart()
if not chart:
    print("错误:无法获取谱面")
    return

# 继续处理...

2. 参数验证

在使用 sys.argv 前检查长度和类型:

import sys

if len(sys.argv) < 3:
    print("错误:缺少参数")
    return

try:
    value = float(sys.argv[1])
except ValueError:
    print("错误:参数必须是数字")
    return

3. 使用异常处理

捕获可能的错误,提供友好的错误信息:

try:
    chart = load_chart_from_file("path/to/chart.txt")
    # 处理谱面...
except FileNotFoundError:
    print("错误:文件不存在")
except Exception as e:
    print(f"错误:{e}")

4. 输出详细信息

使用 print() 输出处理结果,信息会显示在 RCT 状态栏:

print(f"处理完成:保留了 {len(chart.notes)} 个音符")
print(f"时间范围:{min_time}ms - {max_time}ms")

5. 保存前排序

修改音符后调用 chart.sort() 确保顺序正确:

chart.add_note(Note.TAP, 1000, 45)
chart.add_note(Note.TAP, 500, 90)

chart.sort()  # 重要!确保按时间排序
save_current_chart(chart)

6. 备份重要谱面

在测试新脚本前先备份谱面文件:

from rct_api import get_current_chart, save_chart_to_file

chart = get_current_chart()
if chart:
    # 创建备份
    save_chart_to_file(chart, "backup/chart_backup.txt")
    
    # 然后进行修改...

代码规范

文件结构

推荐的脚本文件结构:

# Description: 脚本描述
# Args: 参数说明(可选)
# UI: UI配置(可选)

import sys
import json
from rct_api import get_current_chart, save_current_chart, Note

def main():
    """主函数"""
    # 参数检查
    if len(sys.argv) < 2:
        print("错误:缺少参数")
        return
    
    # 获取谱面
    chart = get_current_chart()
    if not chart:
        print("错误:无法获取谱面")
        return
    
    # 处理逻辑
    try:
        # ... 你的代码 ...
        
        # 保存
        save_current_chart(chart)
        print("处理完成")
    except Exception as e:
        print(f"错误:{e}")

if __name__ == "__main__":
    main()

命名规范

  • 文件名:使用小写字母和下划线,如 shift_time.py
  • 函数名:使用小写字母和下划线,如 process_notes()
  • 变量名:使用描述性名称,如 start_time 而不是 st

注释规范

# 单行注释:说明代码意图

"""
多行注释或文档字符串:
详细说明函数功能、参数和返回值
"""

def filter_by_time(chart, start, end):
    """
    按时间范围过滤音符
    
    Args:
        chart: Chart 对象
        start: 起始时间(毫秒)
        end: 结束时间(毫秒)
    """
    chart.filter_notes_by_time(start, end)

性能优化

1. 避免重复操作

不推荐:

for i in range(len(chart.notes)):
    note = chart.notes[i]
    # 处理...

推荐:

for note in chart.notes:
    # 处理...

2. 批量处理

不推荐:

for i in range(100):
    chart.add_note(Note.TAP, i * 1000, 45)
    chart.sort()  # 每次都排序,效率低
    save_current_chart(chart)

推荐:

for i in range(100):
    chart.add_note(Note.TAP, i * 1000, 45)

chart.sort()  # 只排序一次
save_current_chart(chart)

3. 使用列表推导式

不推荐:

filtered_notes = []
for note in chart.notes:
    if note.type == Note.TAP:
        filtered_notes.append(note)
chart.notes = filtered_notes

推荐:

chart.notes = [note for note in chart.notes if note.type == Note.TAP]

调试技巧

1. 输出调试信息

print(f"[DEBUG] 音符数量: {len(chart.notes)}")
print(f"[DEBUG] 第一个音符: type={chart.notes[0].type}, time={chart.notes[0].time}")

2. 分步测试

将复杂操作分解为多个步骤,逐步测试:

# 步骤 1:只读取和显示信息
chart = get_current_chart()
print(f"音符数量: {len(chart.notes)}")

# 步骤 2:添加少量测试数据
# chart.add_note(Note.TAP, 1000, 45)
# save_current_chart(chart)

# 步骤 3:完整功能
# ... 完整代码 ...

3. 使用条件导入

在开发时可以添加本地测试代码:

DEBUG = True  # 开发时设为 True

if DEBUG:
    print("[DEBUG] 进入调试模式")
    # 使用测试数据...
else:
    chart = get_current_chart()

常见错误

1. 忘记检查 None

❌ 错误:

chart = get_current_chart()
print(len(chart.notes))  # 如果 chart 是 None 会报错

✅ 正确:

chart = get_current_chart()
if chart:
    print(len(chart.notes))
else:
    print("错误:无法获取谱面")

2. 参数类型错误

❌ 错误:

offset = sys.argv[1]  # 这是字符串
chart.shift_time(offset)  # 需要数字

✅ 正确:

offset = float(sys.argv[1])  # 转换为浮点数
chart.shift_time(offset)

3. 忘记排序

❌ 错误:

chart.add_note(Note.TAP, 3000, 90)
chart.add_note(Note.TAP, 1000, 45)
save_current_chart(chart)  # 顺序混乱

✅ 正确:

chart.add_note(Note.TAP, 3000, 90)
chart.add_note(Note.TAP, 1000, 45)
chart.sort()  # 排序
save_current_chart(chart)

4. 修改列表时的迭代问题

❌ 错误:

for note in chart.notes:
    if note.type == Note.BOMB:
        chart.notes.remove(note)  # 迭代时修改列表

✅ 正确:

chart.notes = [note for note in chart.notes if note.type != Note.BOMB]

注意事项

时间单位

  • 统一使用毫秒 (ms) 作为时间单位
  • 角度范围为 0-360 度
# 1 秒 = 1000 毫秒
one_second = 1000

# 半圈 = 180 度
half_circle = 180

自定义 UI 配置

  • JSON 配置必须在同一行(单行注释格式)
  • 或使用三引号字符串格式(推荐)
  • 所有 default_value 都是字符串格式
# 单行格式
# UI: {"fields":[{"name":"value","field_type":"number","label":"值:","default_value":"10","options":[]}]}

# 或三引号格式(推荐)
"""UI:{
  "fields": [...]
}"""

文件命名

  • 不要使用中文或特殊字符
  • 使用小写字母和下划线
  • 使用描述性名称

保存操作

  • 修改谱面后务必调用 save_current_chart() 保存
  • 保存操作无法撤销
  • 重要谱面请先备份

安全建议

1. 数据验证

始终验证用户输入:

if start_time < 0:
    print("错误:起始时间不能为负数")
    return

if end_time <= start_time:
    print("错误:结束时间必须大于起始时间")
    return

2. 边界检查

if len(chart.notes) == 0:
    print("警告:谱面没有音符")
    return

if len(chart.bpm) == 0:
    print("警告:谱面没有 BPM 信息")
    return

3. 限制操作范围

# 限制生成的音符数量
MAX_NOTES = 10000

if count > MAX_NOTES:
    print(f"错误:音符数量不能超过 {MAX_NOTES}")
    return

进阶技巧

1. 使用配置文件

import json

# 读取配置
with open("config.json", "r") as f:
    config = json.load(f)

default_bpm = config.get("default_bpm", 120)

2. 命令行参数解析

使用 argparse 实现更友好的参数处理:

import argparse

parser = argparse.ArgumentParser(description="音符时间平移工具")
parser.add_argument("offset", type=float, help="时间偏移量(毫秒)")
parser.add_argument("--verbose", action="store_true", help="显示详细信息")

args = parser.parse_args()
offset = args.offset

3. 模块化设计

将常用功能封装成函数:

def validate_time_range(start, end):
    """验证时间范围"""
    if start < 0 or end < 0:
        return False, "时间不能为负数"
    if end <= start:
        return False, "结束时间必须大于起始时间"
    return True, ""

# 使用
valid, error = validate_time_range(start, end)
if not valid:
    print(f"错误:{error}")
    return

相关资源

  • 快速开始 - 入门指南
  • 核心API - API 函数参考
  • 示例脚本 - 实用示例代码
最后更新: 2026/1/12 01:03
Prev
示例脚本